Znajdziesz wiele samouczków na temat pasków menu w HTML, ale w tym konkretnym (choć ogólnym przypadku IMHO) nie znalazłem żadnego przyzwoitego rozwiązania:
# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE #
# ^ ^ #
- Istnieje zmienna liczba pozycji menu zawierających tylko tekst, a układ strony jest płynny.
- Pierwsza pozycja menu powinna być wyrównana do lewej, a ostatnia pozycja menu powinna być wyrównana do prawej.
- Pozostałe pozycje należy optymalnie rozłożyć na pasku menu.
- Liczba jest różna, więc nie ma szansy na wstępne obliczenie optymalnych szerokości.
Zwróć uwagę, że TABELA również tutaj nie będzie działać:
- Jeśli wyśrodkujesz wszystkie niszczyciele czołgów, pierwszy i ostatni przedmiot nie będą poprawnie ustawione.
- Jeśli wyrównasz do lewej i do prawej pierwszy resp. ostatnie elementy odstępy będą nieoptymalne.
Czy to nie dziwne, że nie ma oczywistego sposobu zaimplementowania tego w czysty sposób za pomocą HTML i CSS?
span
zamiasthr
! To naprawdę nie działa, HR zajmuje widoczną przestrzeń - użyj,#menu { border: solid 1px green; }
aby potwierdzić. Ponadtodisplay: inline-block;
nie działa w IE (... 7? CompatibilityView?) Dla elementów, które nie są naturalnie elementami wbudowanymi. HR jest elementem blokowym, więc domyślam się, że inline-block nie działa dla HR w IE. W każdym razie, rozpiętość.Ok, to rozwiązanie nie działa na IE6 / 7 z powodu braku wsparcia dla
:before
/:after
, ale: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>
Powodem, dla którego mam tag jako znacznik, jest
inline-block
to, że nie chcę, aby słowa w środku były również uzasadnione, a także nie chcę używać nierozdzielających spacji.źródło
text-justify: distribute-all-lines;
doul
selektora. Wydaje się, że jest to zastrzeżony element IE.width: 100%
zamiastmargin-left: 100%
:ul:after{content:""; margin-left:100%;}
Mam rozwiązanie. Działa w FF, IE6, IE7, Webkit itp.
Upewnij się, że nie wstawiłeś żadnych spacji przed zamknięciem
span.inner
. IE6 się zepsuje.Możesz opcjonalnie podać
.outer
szerokość.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>
źródło
.outer
line-height: 0
wymusza, aby wysokość listy była renderowana tak, jakby składała się z jednej linii.Działa z przeglądarką Opera, Firefox, Chrome i IE
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; }
źródło
jeszcze inne rozwiązanie. Nie miałem opcji, aby zająć się HTML, dodając wyróżnioną klasę itp., Więc znalazłem czysty sposób CSS.
Działa w Chrome, Firefox, Safari… nie wiem o IE.
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>
źródło
Zrobić to
<p>
ztext-align: justify
?Aktualizacja : Nevermind. To w ogóle nie działa, jak myślałem.
Aktualizacja 2 : Obecnie nie działa w żadnej przeglądarce innej niż IE, ale CSS3 obsługuje to w postaci
text-align-last
źródło
text-align-last
działa w każdej przeglądarce innej niż Safari . Powinien to być potencjalny przeciwnik podejścia flexbox lub hack span .W przypadku przeglądarek opartych na Gecko wymyśliłem to rozwiązanie. To rozwiązanie nie działa z przeglądarkami WebKit, chociaż (np. Chromium, Midori, Epiphany), nadal pokazują one spację na końcu ostatniego elementu.
Umieściłem pasek menu w uzasadnionym akapicie . Problem polega na tym, że z oczywistych powodów ostatnia linijka uzasadnionego akapitu nie będzie uzasadniona. Dlatego dodaję szeroki niewidoczny element (np. Img), który gwarantuje, że akapit ma co najmniej dwie linie długości.
Teraz pasek menu jest wyrównywany przez ten sam algorytm, którego używa przeglądarka do justowania zwykłego tekstu.
Kod:
<div style="width:500px; background:#eee;"> <p style="text-align:justify"> <a href="#">THE MENU ITEMS</a> <a href="#">SHOULD BE</a> <a href="#">JUSTIFIED</a> <a href="#">JUST AS</a> <a href="#">PLAIN TEXT</a> <a href="#">WOULD 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>
Uwaga: Czy zauważyłeś, że oszukiwałem? Aby dodać element wypełniający spację, muszę zgadnąć co do szerokości paska menu. Więc to rozwiązanie nie jest całkowicie zgodne z zasadami.
źródło
Tekst jest justowany tylko wtedy, gdy zdanie w naturalny sposób powoduje podział wiersza. Wszystko, co musisz zrobić, to naturalnie wymusić przerwanie linii i ukryć to, co jest w drugiej linii:
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"> </li> </ul>
Element li.break musi znajdować się w tej samej linii, co ostatnia pozycja menu i musi zawierać jakąś zawartość (w tym przypadku nierozdzielającą spację), w przeciwnym razie w niektórych przeglądarkach, jeśli nie znajduje się w tej samej linii, zobaczysz małe dodatkowa spacja na końcu linii, a jeśli nie zawiera treści, jest ignorowana, a linia nie jest wyjustowana.
Przetestowano w IE7, IE8, IE9, Chrome, Firefox 4.
źródło
jeśli chcesz korzystać z javascript, który jest możliwy (ten skrypt jest oparty na 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>
i 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>
i ostatni 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>
źródło
Prostsze znaczniki, przetestowane w przeglądarce 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>
i 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; }
Przykład na żywo .
źródło
Można to doskonale osiągnąć poprzez staranne pomiary i selektor ostatniego dziecka.
ul li { margin-right:20px; } ul li:last-child { margin-right:0; }
źródło
Wiem, że oryginalne pytanie określało HTML + CSS, ale nie było w nim wyraźnie napisane brak javascript ;)
Starając się, aby css i znaczniki były tak czyste, jak to tylko możliwe, i jak najbardziej znaczące semantycznie (używając UL jako menu), wpadłem na tę sugestię. Prawdopodobnie nie jest idealny, ale może być dobrym punktem wyjścia:
<!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>
źródło