HTML + CSSの水平メニューを*本当に*正当化するにはどうすればよいですか?


86

HTMLのメニューバーにはたくさんのチュートリアルがありますが、この特定の(IMHOの一般的な)ケースでは、適切な解決策は見つかりませんでした。

#  THE MENU ITEMS    SHOULD BE    JUSTIFIED     JUST AS    PLAIN TEXT     WOULD BE  #
#  ^                                                                             ^  #
  • テキストのみのメニュー項目の数はさまざまで、ページレイアウトは流動的です。
  • 最初のメニュー項目は左揃えで、最後のメニュー項目は右揃えである必要があります。
  • 残りの項目は、メニューバーに最適に配置する必要があります。
  • 数はさまざまであるため、最適な幅を事前に計算する機会はありません。

TABLEはここでも機能しないことに注意してください。

  • すべてのTDを中央に配置すると、最初と最後のアイテムが正しく配置されません。
  • 最初の応答を左揃えおよび右揃えにした場合。最後の項目では、間隔は最適ではありません。

HTMLとCSSを使用してこれをクリーンな方法で実装する明白な方法がないのは不思議ではありませんか?

回答:


43

現代的なアプローチ-フレックスボックス

今すぐことCSS3のflexboxesを持って、より良いブラウザのサポートを、私たちの一部は最終的にそれらを使用して起動することができます。ブラウザのカバレッジを増やすには、ベンダープレフィックスを追加するだけですです。

この例では、あなただけの親要素のセットでしょうdisplayにしflex、その後、変更justify-contentプロパティをどちらかにspace-betweenか、space-around子供のフレキシボックスアイテム間や周りのスペースを追加するために。

使用justify-content: space-between- ここの例)

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-between;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>


使用justify-content: space-around- (ここの例)

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-around;
}
<ul class="menu">
    <li>Item One</li>
    <li>Item Two</li>
    <li>Item Three Longer</li>
    <li>Item Four</li>
</ul>


83

最も簡単な方法は、行の最後に、残りの使用可能なスペースよりも多くを占める要素を挿入して非表示にすることにより、行を強制的に分割することです。私はspanこれを次のような単純な要素で非常に簡単に達成しました:

#menu {
  text-align: justify;
}

#menu * {
  display: inline;
}

#menu li {
  display: inline-block;
}

#menu span {
  display: inline-block;
  position: relative;
  width: 100%;
  height: 0;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 2</a></li>
  </ul>
  <span></span>
</div>

#menu spanセレクター内のすべてのがらくたは(私が見つけた限り)ほとんどのブラウザーを満足させるために必要です。span要素の幅を100%に強制する必要がありdisplay: inline-blockます。これは、ルールによりインライン要素と見なされるため、改行が発生するはずです。inline-blockまた、次のspanようなブロックレベルのスタイルルールを可能にしますwidth、要素がメニューと一致せず、メニューが改行されるます。

もちろんspan、ユースケースやデザインに合わせて幅を調整する必要がありますが、一般的な考え方を理解し、それを適応させることができれば幸いです。


1
!のspan代わりにを使用すると機能するようですhrそれは実際には機能していません。HRは目に見えるスペースを占めています-#menu { border: solid 1px green; }確認に使用してください。また、display: inline-block;自然にインライン要素ではない要素のIE(... 7?CompatibilityView?)では機能しません。HRはブロック要素であるため、IEのHRではインラインブロックは機能しないと思います。とにかく、スパン。
ANevesは、SEは悪だと考えています2010

9
うまく機能しますが、各スペースを&ensp;に置き換えると、結果はよりきれいになります。(nスペース)、メニューとアイテムと1が近くにあるようにします。&nbsp; サファリでは動作しません。
yitwail 2011

15
壁に頭をぶつけて1時間以上過ごし、なぜこれがうまくいかなかったのかを理解しようとしました。答えは、タグの間に空白が必要だったということです。私はWordPressで作業していますが、wp_page_menuには各<li> </ li>の後に改行が含まれていません。preg_replaceを使用してそれらを追加し、現在は機能しています。Fwewww
Greg Perham

1
最近これを機能させるには、それをサポートするブラウザのLIでdisplay:inline-blockを使用し、display:inlineを使用してスペースを&nbsp;に置き換える必要があります。それをサポートしていないブラウザで。また、ie7はインラインブロックをサポートしていないため、force-wrapタグでインラインを使用し、ラップを強制するのに十分な数を押し込む必要があります。
Joren 2012

1
Jorenのコメントを明確にするために、ULはインラインであり、LIはインラインブロックである必要があります。
モス

12

[OK]を、このソリューションは、ためのサポートの欠如のため、IE6 / 7で動作しない:before/ :after、しかし:

ul {
  text-align: justify;
  list-style: none;
  list-style-image: none;
  margin: 0;
  padding: 0;
}
ul:after {
  content: "";
  margin-left: 100%;
}
li {
  display: inline;
}
a {
  display: inline-block;
}
<div id="menu">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 2</a></li>
    <li><a href="#">Menu item 3</a></li>
    <li><a href="#">Menu item 4</a></li>
    <li><a href="#">Menu item 5</a></li>
  </ul>
</div>

タグをとして使用するinline-block理由は、内部の単語も正当化されたくないためです。また、改行なしのスペースも使用したくないためです。


ありがとう!あなたの魂は要点に達している。質問を開始する場合は、回答としてマークします。
アンドレビンスキー2014年

これをIEで機能させるのに問題がありました。グーグルランドで数時間過ごした後、私はついにこのブログ投稿を見つけました:kristinlbradley.wordpress.com/2011/09/15/…最後にトリックをしtext-justify: distribute-all-lines;たのはulセレクターに追加することでした。独自仕様のIEのもののようです。
maryisdead 2014

これが重要かどうかはわかりませんが、width: 100%代わりに使用しましたmargin-left: 100%ul:after{content:""; margin-left:100%;}
Eugene Song

8

解決策を得ました。FF、IE6、IE7、Webkitなどで動作します。

を閉じる前に、空白を入れないようにしてくださいspan.inner。IE6は壊れます。

オプション.outerで幅を指定できます

.outer {
  text-align: justify;
}
.outer span.finish {
  display: inline-block;
  width: 100%;
}
.outer span.inner {
  display: inline-block;
  white-space: nowrap;
}
<div class="outer">
  <span class="inner">THE MENU ITEMS</span>
  <span class="inner">SHOULD BE</span>
  <span class="inner">JUSTIFIED</span>
  <span class="inner">JUST AS</span>
  <span class="inner">PLAIN TEXT</span>
  <span class="inner">WOULD BE</span>
  <span class="finish"></span>
</div>


私にとって、このソリューションはGeckoで正常に機能しますが、WebKitブラウザーでは機能しません(Chromium、Midori、Epiphanyでテスト済み):WebKitでは、最後の項目の後に末尾のスペースがあります。
フライト

各スパンの間に空白文字が1文字だけあり、最後のインナーとフィニッシュの間に2文字あることを確認してください。それがうまくいかない場合は、空白をいじってください。webkitにバグがあります。
mikelikespie 2010

1
.outer {text-align:justify} .outer span.finish {display:inline-block; 幅:100%} .outer span.inner {表示:インラインブロック; white-space:nowrap} IE6およびIE7では機能しません。
ビンヤミン2010

.outer line-height: 0力を与えると、リストの高さが1行で構成されているかのようにレンダリングされます。
kontur 2014年


3

さらに別の解決策。区別されたクラスを追加するなど、htmlに取り組むオプションがなかったので、純粋なcssの方法を見つけました。

Chrome、Firefox、Safariで動作します。IEについてはわかりません。

テスト:http//jsfiddle.net/c2crP/1

ul {
  margin: 0; 
  padding: 0; 
  list-style: none; 
  width: 200px; 
  text-align: justify; 
  list-style-type: none;
}
ul > li {
  display: inline; 
  text-align: justify; 
}

/* declaration below will add a whitespace after every li. This is for one line codes where no whitespace (of breaks) are present and the browser wouldn't know where to make a break. */
ul > li:after {
  content: ' '; 
  display: inline;
}

/* notice the 'inline-block'! Otherwise won't work for webkit which puts after pseudo el inside of it's parent instead of after thus shifting also the parent on next line! */
ul > li:last-child:after {
  display: inline-block;
  margin-left: 100%; 
  content: ' ';
}
<ul>
  <li><a href="#">home</a></li>
  <li><a href="#">exposities</a></li>
  <li><a href="#">werk</a></li>
  <li><a href="#">statement</a></li>
  <li><a href="#">contact</a></li>
</ul>


2

それ作る<p>text-align: justify

更新:気にしないでください。私が思っていたように、それはまったく機能しません。

アップデート2:現在IE以外のブラウザでは動作しませんが、CSS3は次の形式でこれをサポートしていますtext-align-last


それは速かった!私自身の解決策はユニークだと思いましたが、あなたはほんの数秒で最初と同じようなものを思いついたのです。
フライト


1

Geckoベースのブラウザの場合、私はこのソリューションを思いつきました。このソリューションはWebKitブラウザーでは機能しませんが(Chromium、Midori、Epiphanyなど)、最後の項目の後にスペースが表示されます。

メニューバーを両端揃えの段落に配置しました。問題は、明らかな理由により、正当化された段落の最後の行が正当化されないことです。したがって、段落が少なくとも2行の長さであることを保証する、幅の広い非表示要素(imgなど)を追加します。

これで、メニューバーは、ブラウザがプレーンテキストを揃えるために使用するのと同じアルゴリズムによって揃えられます。

コード:

<div style="width:500px; background:#eee;">
 <p style="text-align:justify">
  <a href="#">THE&nbsp;MENU&nbsp;ITEMS</a>
  <a href="#">SHOULD&nbsp;BE</a>
  <a href="#">JUSTIFIED</a>
  <a href="#">JUST&nbsp;AS</a>
  <a href="#">PLAIN&nbsp;TEXT</a>
  <a href="#">WOULD&nbsp;BE</a>
  <img src="/Content/Img/stackoverflow-logo-250.png" width="400" height="0"/>
 </p>
 <p>There's an varying number of text-only menu items and the page layout is fluid.</p>
 <p>The first menu item should be left-aligned, the last menu item should be right-aligned. The remaining items should be spread optimal on the menu bar.</p>
 <p>The number is varying,so there's no chance to pre-calculate the optimal widths.</p>
 <p>Note that a TABLE won't work here as well:</p>
 <ul>
  <li>If you center all TDs, the first and the last item aren't aligned correctly.</li>
  <li>If you left-align and right-align the first resp. the last items, the spacing will be sub-optimal.</li>
 </ul>
</div>

備考:私がだまされたことに気づきましたか?スペースフィラー要素を追加するには、メニューバーの幅を推測する必要があります。したがって、このソリューションは完全にルールに依存しているわけではありません。


list-items ...にdisplay:inlineを設定した場合は、ここでもリストを使用できます。リストはメニューの方が一般的です。
Andrew Vit

@Andrew Vit:その通りです。これは主に、asbjornuのソリューションが示唆していることでもあります。
フライト

@flight、私の答えが解決策だと思うなら、それを1つとしてマークしてください。現在、問題は解決されていないようです。そうでない場合は、見つけた解決策を私たちに提供するか、提供された回答のいずれかを問題の解決策としてマークしてください。:-)
アスビョルンUlsberg

1

文が自然に改行を引き起こす場合にのみ、テキストは正当化されます。したがって、必要なのは、自然に改行を強制し、2行目の内容を非表示にすることだけです。

CSS:

ul {
  text-align: justify;
  width: 400px;
  margin: 0;
  padding: 0;
  height: 1.2em;
  /* forces the height of the ul to one line */
  overflow: hidden;
  /* enforces the single line height */
  list-style-type: none;
  background-color: yellow;
}

ul li {
  display: inline;
}

ul li.break {
  margin-left: 100%;
  /* use e.g. 1000px if your ul has no width */
}

HTML:

<ul>
  <li><a href="/">The</a></li>
  <li><a href="/">quick</a></li>
  <li><a href="/">brown</a></li>
  <li><a href="/">fox</a></li>
  <li class="break">&nbsp;</li>
</ul>

li.break要素は最後のメニュー項目と同じ行にある必要があり、コンテンツ(この場合は改行なしスペース)が含まれている必要があります。そうでない場合、一部のブラウザーでは、同じ行にない場合は小さな文字が表示されます。行の終わりに余分なスペースがあり、コンテンツが含まれていない場合は無視され、行は正当化されません。

IE7、IE8、IE9、Chrome、Firefox4でテスト済み。


0

可能なjavascriptを使用する場合(このスクリプトはmootoolsに基づいています)

<script type="text/javascript">//<![CDATA[
    window.addEvent('load', function(){
        var mncontainer = $('main-menu');
        var mncw = mncontainer.getSize().size.x;
        var mnul = mncontainer.getFirst();//UL
        var mnuw = mnul.getSize().size.x;
        var wdif = mncw - mnuw;
        var list = mnul.getChildren(); //get all list items
        //get the remained width (which can be positive or negative)
        //and devided by number of list item and also take out the precision
        var liwd = Math.floor(wdif/list.length);
        var selw, mwd=mncw, tliw=0;
        list.each(function(el){
            var elw = el.getSize().size.x;
            if(elw < mwd){ mwd = elw; selw = el;}
            el.setStyle('width', elw+liwd);
            tliw += el.getSize().size.x;
        });
        var rwidth = mncw-tliw;//get the remain width and set it to item which has smallest width
        if(rwidth>0){
            elw = selw.getSize().size.x;
            selw.setStyle('width', elw+rwidth);
        }
    });
    //]]>
</script>

とcss

<style type="text/css">
    #main-menu{
        padding-top:41px;
        width:100%;
        overflow:hidden;
        position:relative;
    }
    ul.menu_tab{
        padding-top:1px;
        height:38px;
        clear:left;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        left:50%;
        text-align:center;
    }
    ul.menu_tab li{
        display:block;
        float:left;
        list-style:none;
        margin:0;
        padding:0;
        position:relative;
        right:50%;
    }
    ul.menu_tab li.item7{
        margin-right:0;
    }
    ul.menu_tab li a, ul.menu_tab li a:visited{
        display:block;
        color:#006A71;
        font-weight:700;
        text-decoration:none;
        padding:0 0 0 10px;
    }
    ul.menu_tab li a span{
        display:block;
        padding:12px 10px 8px 0;
    }
    ul.menu_tab li.active a, ul.menu_tab li a:hover{
        background:url("../images/bg-menutab.gif") repeat-x left top;
        color:#999999;
    }
    ul.menu_tab li.active a span,ul.menu_tab li.active a.visited span, ul.menu_tab li a:hover span{
        background:url("../images/bg-menutab.gif") repeat-x right top;
        color:#999999;
    }
</style>

そして最後のhtml

<div id="main-menu">
    <ul class="menu_tab">
        <li class="item1"><a href="#"><span>Home</span></a></li>
        <li class="item2"><a href="#"><span>The Project</span></a></li>
        <li class="item3"><a href="#"><span>About Grants</span></a></li>
        <li class="item4"><a href="#"><span>Partners</span></a></li>
        <li class="item5"><a href="#"><span>Resources</span></a></li>
        <li class="item6"><a href="#"><span>News</span></a></li>
        <li class="item7"><a href="#"><span>Contact</span></a></li>
    </ul>
</div>

0

よりシンプルなマークアップ、Opera、FF、Chrome、IE7、IE8でテスト済み:

<div class="nav">
  <a href="#" class="nav_item">nav item1</a>
  <a href="#" class="nav_item">nav item2</a>
  <a href="#" class="nav_item">nav item3</a>
  <a href="#" class="nav_item">nav item4</a>
  <a href="#" class="nav_item">nav item5</a>
  <a href="#" class="nav_item">nav item6</a>
  <span class="empty"></span>
</div>

およびcss:

.nav {
  width: 500px;
  height: 1em;
  line-height: 1em;
  text-align: justify;
  overflow: hidden;
  border: 1px dotted gray;
}
.nav_item {
  display: inline-block;
}
.empty {
  display: inline-block;
  width: 100%;
  height: 0;
}

実例


-1

これは、いくつかの注意深い測定と最後の子セレクターによって完全に達成できます。

ul li {
margin-right:20px;
}
ul li:last-child {
margin-right:0;
}

4
テキストがどこでも同じようにレンダリングされるわけではなく、ピクセルがずれていると、メニューが壊れてしまうことに注意してください。これは、画像のような固定幅の要素でのみ機能します。
fregante 2011年

-2

元の質問でHTML + CSSが指定されていることは知っていますが、JavaScriptが特に指定されていません;)

cssとマークアップを可能な限りクリーンに保ち、(メニューにULを使用して)可能な限り意味的に意味のあるものにしようと、私はこの提案を思いつきました。おそらく理想的ではありませんが、それは良い出発点かもしれません:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

    <head>
        <title>Kind-of-justified horizontal menu</title>

        <style type="text/css">
        ul {
            list-style: none;
            margin: 0;
            padding: 0;
            width: 100%;
        }

        ul li {
            display: block;
            float: left;
            text-align: center;
        }
        </style>

        <script type="text/javascript">
            setMenu = function() {
                var items = document.getElementById("nav").getElementsByTagName("li");
                var newwidth = 100 / items.length;

                for(var i = 0; i < items.length; i++) {
                    items[i].style.width = newwidth + "%";
                }
            }
        </script>

    </head>

    <body>

        <ul id="nav">
            <li><a href="#">first item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
            <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
            <li><a href="#">last item</a></li>
        </ul>

        <script type="text/javascript">
            setMenu();
        </script>

    </body>

</html>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.