HTML + CSS'de yatay bir menüyü * gerçekten * nasıl yaslayabilirim?


87

HTML'deki menü çubuklarında çok sayıda öğretici buluyorsunuz, ancak bu özel (IMHO jenerik olsa da) durum için iyi bir çözüm bulamadım:

#  THE MENU ITEMS    SHOULD BE    JUSTIFIED     JUST AS    PLAIN TEXT     WOULD BE  #
#  ^                                                                             ^  #
  • Değişken sayıda salt metin menü öğesi vardır ve sayfa düzeni akıcıdır.
  • İlk menü öğesi sola, son menü öğesi sağa hizalanmalıdır.
  • Kalan öğeler, menü çubuğunda en uygun şekilde yayılmalıdır.
  • Sayı değişiyor, bu nedenle optimum genişlikleri önceden hesaplama şansı yok.

Bir TABLO'nun burada da çalışmayacağını unutmayın:

  • Tüm tank avcılarını ortalarsanız, ilk ve son öğe doğru şekilde hizalanmaz.
  • İlk yanıtı sola ve sağa hizalarsanız. son öğeler, aralık optimumun altında olacaktır.

Bunu HTML ve CSS kullanarak temiz bir şekilde uygulamanın bariz bir yolu olmaması garip değil mi?

Yanıtlar:


43

Modern Yaklaşım - Flexbox'lar !

Artık CSS3 esnek kutuları daha iyi tarayıcı desteğine sahip olduğundan , bazılarımız sonunda bunları kullanmaya başlayabiliriz. Daha fazla tarayıcı kapsamı için ek satıcı önekleri eklemeniz yeterlidir .

Bu örnekte, ana öğenin displaydeğerini olarak ayarlayabilir flexve ardından justify-contentözelliği , alt flexbox öğelerinin arasına veya çevresine boşluk eklemek için space-betweenveya space-aroundolarak değiştirirsiniz .

Kullanarakjustify-content: space-between - ( burada örnek) :

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>


Kullanarakjustify-content: space-around - (burada örnek) :

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

Yapılması gereken en basit şey, satırın sonuna, kalan boş alandan daha fazlasını kaplayacak bir eleman ekleyerek ve sonra onu gizleyerek çizgiyi kırmaya zorlamaktır. Bunu oldukça basit bir spanunsurla başardım :

#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Çoğu tarayıcıyı memnun etmek için seçicinin içindeki tüm önemsiz şeyler (bulduğum kadarıyla) gereklidir. spanÖğenin genişliğini % 100'e zorlamalı , bu da display: inline-blockkural nedeniyle bir satır içi öğe olarak kabul edildiğinden satırın kesilmesine neden olmalıdır . inline-blockaynı zamanda öğenin menüye uymamasına ve dolayısıyla menünün satır kırılmasına neden olan spanblok seviyesi stil kurallarını mümkün kılar width.

Elbette genişliğini spankullanım durumunuza ve tasarımınıza göre ayarlamanız gerekiyor , ancak umarım genel fikri alırsınız ve onu uyarlayabilirsiniz.


1
Bir spanyerine a kullanırsanız işe yarıyor gibi görünüyor hr! Gerçekten işe yaramıyor, İK görünür alanı kaplıyor - #menu { border: solid 1px green; }onaylamak için kullanın . Ayrıca, display: inline-block;doğal olarak satır içi öğeler olmayan öğeler için IE (... 7? CompatibilityView?) Üzerinde çalışmaz. İK bir blok unsurdur, bu yüzden inline-block'un IE'de İK için çalışmadığını tahmin ediyorum. Her neyse, yayılma.
ANeves, SE'nin kötü olduğunu düşünüyor

9
harika çalışıyor, ancak her boşluğu & ensp; ile değiştirirseniz sonuçlar daha güzel olur. (n boşluk), böylece Menü ve öğe ve 1 birbirine yakın kalır. & nbsp; safaride çalışmaz.
yitwail

15
Bunun neden benim için işe yaramadığını anlamaya çalışarak, kafamı duvara vurarak bir saatten fazla zaman harcadım. Cevap, etiketler arasında beyaz boşluğa ihtiyacım olması. WordPress'te çalışıyorum ve wp_page_menu her <li> </li> 'den sonra satır sonu içermiyor. Preg_replace kullanarak onları ekledi ve şimdi çalışıyor. Fwewww
Greg Perham

1
Bu günlerde bunun işe yaraması için display: onu destekleyen tarayıcılardaki LI'lerde inline-block kullanmalı ve display: inline ve boşluklarla & nbsp; desteklemeyen tarayıcılarda. Ayrıca ie7, satır içi bloğu desteklemediğinden, zorla sarma etiketinizde satır içi kullanmanız ve sarmayı zorlamak için içine yeterince & nbsp; itmeniz gerekir.
Joren

1
Joren'in yorumunu açıklığa kavuşturmak için UL'nin hala satır içi ve LI'nin satır içi bloğu olması gerekiyor.
Moss

12

Tamam, bu çözüm yüzünden desteğiyle eksikliği nedeniyle, IE6 / 7 çalışmıyor :before/ :afterama:

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>

A etiketini bir etiket olarak inline-blockkullanmamın nedeni, içindeki kelimelerin de haklı çıkmasını istememem ve bölünemez boşluklar kullanmak istemememdir.


Teşekkürler! Ruhun noktaya geldi. Soruyu başlatacak olsaydım, cevap olarak işaretlerdim.
Andrevinsky

Bunu IE'de çalıştırmakta sorun yaşadım. Google topraklarında geçirilen birkaç saatten sonra nihayet şu blog gönderisini buldum: kristinlbradley.wordpress.com/2011/09/15/… Sonunda hile, seçiciye eklemek text-justify: distribute-all-lines;oldu ul. Tescilli IE öğeleri gibi görünüyor.
maryisdead

Bunun önemli olup olmadığından emin değilim, ama width: 100%yerine şunu kullandım margin-left: 100%: ul:after{content:""; margin-left:100%;}
Eugene Song

8

Bir çözüm buldum. FF, IE6, IE7, Webkit vb. İle çalışır.

Kapatmadan önce herhangi bir boşluk koymadığınızdan emin olun span.inner. IE6 kırılacak.

İsteğe bağlı olarak .outerbir genişlik verebilirsiniz

.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>


Benim için bu çözüm Gecko ile iyi çalışıyor, ancak WebKit tarayıcılarında (Chromium, Midori, Epiphany ile test edilmiş) çalışmıyor: WebKit ile son öğeden sonra boşluk var.
uçuşu

Her aralık arasında yalnızca bir boşluk karakteri ve son iç ile bitiş arasında iki karakter olduğundan emin olun. Bu boşlukla uğraşmazsa. Webkit'te bir hata var.
mikelikespie

1
.outer {text-align: justify} .outer span.finish {display: inline-block; genişlik:% 100} .outer span.inner {display: inline-block; white-space: nowrap} IE6 ve IE7'de çalışmaz.
Binyamin

.outer line-height: 0Listenin yüksekliğini tek satırdan oluşuyormuş gibi gösterilecek kuvvetlere verilmesi .
kontur

4

Opera, Firefox, Chrome ve IE ile çalışır

ul {
   display: table;
   margin: 1em auto 0;
   padding: 0;
   text-align: center;
   width: 90%;
}

li {
   display: table-cell;
   border: 1px solid black;
   padding: 0 5px;
}


3

yine başka bir çözüm. Html'yi ayırt edici sınıflar vb. Eklemek gibi ele alma seçeneğim yoktu, bu yüzden saf bir css yolu buldum.

Chrome, Firefox, Safari'de çalışır. IE hakkında bilgim yok.

Test: 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

İle <p>yap text-align: justify?

Güncelleme : Nevermind. Bu hiç düşündüğüm gibi çalışmıyor.

Güncelleme 2 : Şu anda IE dışındaki tarayıcılarda çalışmıyor, ancak CSS3 bunu şu şekilde destekliyor:text-align-last


Bu kadar hızlı oldu! Kendi çözümümün benzersiz olduğunu düşünmüştüm, ancak birkaç dakika içinde başlamaya benzer bir şey buldunuz.
uçuşu

Şimdi 2016'da text-align-last Safari dışındaki tüm tarayıcılarda çalışıyor . Bu , flexbox yaklaşımının veya span hack'in olası rakibi olmalıdır .
hakatashi

1

Gecko tabanlı tarayıcılar için bu çözümü buldum. Bu çözüm WebKit tarayıcıları ile çalışmaz (örn. Chromium, Midori, Epiphany), yine de son öğeden sonra boşluk gösterirler.

Menü çubuğunu yaslanmış bir paragrafa koydum . Sorun, gerekçeli bir paragrafın son satırının, bariz nedenlerden ötürü gerekçelendirilmemesidir. Bu nedenle, paragrafın en az iki satır uzunluğunda olduğunu garanti eden geniş bir görünmez öğe (örneğin bir img) ekliyorum.

Artık menü çubuğu, tarayıcının düz metni doğrulamak için kullandığı algoritmanın aynısı tarafından doğrulanmıştır.

Kod:

<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>

Not: Hile yaptığımı fark ettiniz mi? Boşluk doldurucu öğesini eklemek için, menü çubuğunun genişliği hakkında biraz tahmin yapmam gerekiyor. Yani bu çözüm tamamen kurallara bağlı değil.


Burada da bir liste kullanmış olabileceğinizi unutmayın, eğer display: inline üzerinde liste öğeleri ... listeleri menüler için daha gelenekseldir.
Andrew Vit

@Andrew Vit: Haklısın. Asbjornu'nun çözümünün de önerdiği çoğunlukla budur.
uçuşu

@flight, cevabımın bir çözüm olduğunu düşünüyorsanız, lütfen tek olarak işaretler misiniz? Şu anda sorunun çözülmemiş gibi görünüyor. Değilse, bulduğunuz çözümü bize sağlamanız veya verilen yanıtlardan herhangi birini sorununuzun çözümü olarak işaretlemeniz iyi olur. :-)
Asbjørn Ulsberg

1

Metin, yalnızca cümle doğal olarak satır kesilmesine neden olursa yaslanır. Yani yapmanız gereken tek şey doğal olarak bir satır sonu zorlamak ve ikinci satırda ne olduğunu gizlemek:

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 öğesi, son menü öğesiyle aynı satırda olmalı ve bir miktar içerik içermelidir (bu durumda bölünemez bir boşluk), aksi takdirde bazı tarayıcılarda, aynı satırda değilse, bazı küçük satırınızın sonunda fazladan boşluk var ve içerik içermiyorsa, o zaman yok sayılır ve satır hizalanmaz.

IE7, IE8, IE9, Chrome, Firefox 4'te test edilmiştir.


0

mümkün olan javascript ile gitmek gerekirse (bu komut dosyası mootoollere dayanmaktadır)

<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>

ve 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>

ve son 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'de test edilen daha basit biçimlendirme:

<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>

ve 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;
}

Canlı örnek .


-1

Bu, bazı dikkatli ölçümler ve son çocuk seçici ile mükemmel bir şekilde sağlanabilir.

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

4
Metnin her yerde aynı şeyi oluşturmadığını, bir pikselin kapalı olduğunu ve bozuk bir menü göreceksiniz. Bu yalnızca resimler gibi sabit genişlikteki öğelerle çalışır.
fregante

-2

Orijinal sorunun HTML + CSS'yi belirttiğini biliyorum, ancak özellikle javascript demedi ;)

CSS'yi ve işaretlemeyi olabildiğince temiz ve anlamsal olarak mümkün olduğunca anlamlı tutmaya çalışarak (menü için UL kullanarak) bu öneriyi buldum. Muhtemelen ideal değil, ancak iyi bir başlangıç ​​noktası olabilir:

<!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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.