Czy lista uporządkowana może dać wynik podobny do 1.1, 1.2, 1.3 (zamiast tylko 1, 2, 3,…) z css?

201

Czy uporządkowana lista może generować wyniki wyglądające jak 1.1, 1.2, 1.3 (zamiast tylko 1, 2, 3, ...) z CSS? Do tej pory używanie list-style-type:decimalzaowocowało tylko 1, 2, 3, a nie 1.1, 1.2., 1.3.

Richard77
źródło
Proponuję porównać przyjętą odpowiedź z odpowiedzią Jakuba Jirutki. Myślę, że ten drugi jest nawet znacznie lepszy.
Frank Conijn,
Eleganckie rozwiązanie. Masz pojęcie, dlaczego Wikipedia używa ul do swoich sekcji treści zamiast tego?
Mattypants
1
@davnicwil Zgadzam się; wygląda na to, że prawdopodobnie właśnie we wrześniu zastosowałem duplikat w niewłaściwej kolejności.
TylerH,
Fajnie, teraz czuję się niezręcznie, ponieważ nigdy nie przyszło mi do głowy, że może to być zwykły błąd - przepraszam!
davnicwil

Odpowiedzi:

289

Możesz użyć do tego liczników :

Poniższe numery arkuszy stylów zagnieżdżają elementy listy jako „1”, „1.1”, „1.1.1” itp.

OL { counter-reset: item }
LI { display: block }
LI:before { content: counters(item, ".") " "; counter-increment: item }

Przykład

ol { counter-reset: item }
li{ display: block }
li:before { content: counters(item, ".") " "; counter-increment: item }
<ol>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
  <li>li element</li>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
</ol>

Aby uzyskać więcej informacji, zobacz Zagnieżdżone liczniki i zakres .

Gumbo
źródło
2
świetna odpowiedź. Jakie jest poparcie tego?
Jason McCreary,
1
@Jason McCreary: Cóż, to wada: liczniki nie są obsługiwane w IE do wersji 8 .
Gumbo,
3
W tym rozwiązaniu brakuje jednej drobnej rzeczy: kropki po numerze elementu. Nie wygląda jak standardowy styl listy. Napraw, dodając kropkę do reguły dla li:before: content: counters(item, ".")". ";
LS
4
To kiepska odpowiedź. To nie działa poprawnie. Sprawdź odpowiedź Jakuba Jirutki poniżej
Pan Pablo
1
@Gumbo Wiem, a odpowiedź Jakuba dała mi prawidłową numerację.
Pan Pablo
236

Żadne z rozwiązań na tej stronie nie działa poprawnie i uniwersalnie dla wszystkich poziomów i długich (zawijanych) akapitów. Naprawdę trudne jest uzyskanie spójnego wcięcia z powodu zmiennej wielkości znacznika (1., 1.2, 1.10, 1.10.5,…); nie można go po prostu „sfałszować”, nawet przy wstępnie obliczonym marginesie / wypełnieniu dla każdego możliwego poziomu wcięcia.

W końcu wymyśliłem rozwiązanie, które faktycznie działa i nie wymaga JavaScript.

Jest testowany na Firefox 32, Chromium 37, IE 9 i Android Browser. Nie działa na IE 7 i wcześniejszych.

CSS:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;    
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") " ";
}

Przykład: Przykład

Wypróbuj na JSFiddle , rozwidl na Gist .

Jakub Jirutka
źródło
1
Dobra robota dla osiągnięcia tego rodzaju wcięcia. Nadal jednak twierdzę, że dwa pierwsze przypadki wcięć, które wymieniłeś, są kwestią preferencji, a nie dobra i zła. Weźmy pod uwagę przypadek 1 i przypadek 2 - ten drugi potrafi przecisnąć się na znacznie więcej poziomach, zanim odstępy stają się niewygodne, a jednocześnie wyglądają całkiem nieźle. Ponadto zarówno MS Word, jak i domyślny styl przeglądarki używają wcięcia 2 przypadku. Myślę, że oni też robią to źle?
Saul Fautley
2
@ saul-fautley To źle pod względem typografii. Twój przykład z szaloną liczbą zagnieżdżonych poziomów pokazuje, że zagnieżdżona numeracja nie jest odpowiednia dla zbyt wielu poziomów, ale jest to dość oczywiste. MS Words nie jest systemem składu, to zwykły procesor dokumentów o słabej typografii. Domyślny styl przeglądarki… och, nie wiesz dużo o typografii, prawda?
Jakub Jirutka
3
To naprawdę działa (technicznie) na wszystkich poziomach i długich akapitach. Jeśli rozsądne jest użycie kilkunastu poziomów, to kolejne pytanie, które nie ma nic wspólnego z rozwiązaniem technicznym. Chodzi o to, że nie musisz predefiniować reguły CSS dla każdego poziomu zagnieżdżenia, jak w przypadku niektórych innych rozwiązań.
Jakub Jirutka
4
Chociaż nie powiedziałbym, że z innymi odpowiedziami jest coś „niewłaściwego”, powiedziałbym, że są one niekompletne. Ta odpowiedź jest na miejscu, a nawet działała w przerażająco dziwnie stylizowanej witrynie, którą zmieniam.
DanielM
2
@tremby: Rozbieżność można rozwiązać poprzez użycie li „display: table-row” zamiast „display: table”. Problemem jest to, że li nie może wtedy używać żadnych marginesów / wypełnień, ponieważ rzędy tabel są zawsze automatycznie sortowane według zawartości. Można to obejść, dodając „li: after” z „display: block”. Zobacz pełny przykład w jsFiddle . Jako dodatkowy bonus dodałem „wyrównanie tekstu: do prawej” do „li: przed”, aby wyrównać liczby do prawej.
mmlr
64

Wybrana odpowiedź jest świetnym początkiem, ale zasadniczo wymusza list-style-position: inside;stylizację elementów listy, co sprawia, że ​​zawijany tekst jest trudny do odczytania. Oto proste obejście, które daje również kontrolę nad marginesem między liczbą a tekstem i wyrównuje liczbę do prawej zgodnie z domyślnym zachowaniem.

ol {
    counter-reset: item;
}
ol li {
    display: block;
    position: relative;
}
ol li:before {
    content: counters(item, ".")".";
    counter-increment: item;
    position: absolute;
    margin-right: 100%;
    right: 10px; /* space between number and text */
}

JSFiddle: http://jsfiddle.net/3J4Bu/

Saul Fautley
źródło
Jednym minusem jest to, że dodaje kropkę na końcu każdego elementu listy.
Davin Studer,
3
@Davin Studer: Dodaje tylko kropkę na końcu każdej liczby, zgodnie z olzachowaniem domyślnym . Można go łatwo usunąć, usuwając ostatni "."z contentwłaściwości, ale dla mnie wygląda to nieco dziwnie.
Saul Fautley,
14

Rozwiązania zamieszczone tutaj nie działały dla mnie dobrze, więc zrobiłem mieszankę odpowiedzi na to pytanie i następujące pytanie: Czy można utworzyć wielopoziomową uporządkowaną listę w języku HTML?

/* Numbered lists like 1, 1.1, 2.2.1... */
ol li {display:block;} /* hide original list counter */
ol > li:first-child {counter-reset: item;} /* reset counter */
ol > li {counter-increment: item; position: relative;} /* increment counter */
ol > li:before {content:counters(item, ".") ". "; position: absolute; margin-right: 100%; right: 10px;} /* print counter */

Wynik:

zrzut ekranu

Uwaga: zrzut ekranu, jeśli chcesz zobaczyć kod źródłowy lub cokolwiek z tego postu: http://estiloasertivo.blogspot.com.es/2014/08/introduccion-running-lean-y-lean.html

chelder
źródło
1
To najlepsza (i najprostsza) działająca odpowiedź z całej strony.
Bruno Toffolo,
6

Uwaga: Użyj CSS, aby utworzyć zagnieżdżoną numerację w nowoczesnej przeglądarce. Zobacz zaakceptowaną odpowiedź. Poniższe informacje dotyczą wyłącznie historii.counters


Jeśli przeglądarka obsługuje contenti counter,

.foo {
  counter-reset: foo;
}
.foo li {
  list-style-type: none;
}
.foo li::before {
  counter-increment: foo;
  content: "1." counter(foo) " ";
}
<ol class="foo">
  <li>uno</li>
  <li>dos</li>
  <li>tres</li>
  <li>cuatro</li>
</ol>

kennytm
źródło
To rozwiązanie kończy się niepowodzeniem, gdy listy są zagnieżdżone.
LS
@LS Zawsze możesz dostosować selektory do swoich potrzeb. .foo > ol > li.
kennytm
1
Chodzi mi o to, że zapisałeś na stałe „1”. w stylu. Co się stanie, gdy podlista jest dzieckiem drugiego elementu na liście nadrzędnej? Chcesz, aby pojawiał się jako „2.”, ale zawsze będzie „1.” ze względu na sposób, w jaki jest tutaj kodowany. Jakie jest rozwiązanie Czy tworzyć nowe zestawy stylów dla każdej możliwej liczby? Nie. Użyj counters()funkcji jak w powyższych przykładach zamiast counter()funkcji.
LS
2
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="author" content="Sandro Alvares - KingRider">
    </head>
    <body>
        <style type="text/css">
            li.title { 
                font-size: 20px; 
                font-weight: lighter; 
                padding: 15px; 
                counter-increment: ordem; 
            }
            .foo { 
                counter-reset: foo; 
                padding-left: 15px; 
            }
            .foo li { 
                list-style-type: none; 
            }
            .foo li:before { 
                counter-increment: foo; 
                content: counter(ordem) "." counter(foo) " "; 
            }
        </style>
        <ol>
            <li class="title">TITLE ONE</li>
            <ol class="foo">
                <li>text 1 one</li>
                <li>text 1 two</li>
                <li>text 1 three</li>
                <li>text 1 four</li>
            </ol>
            <li class="title">TITLE TWO</li>
            <ol class="foo">
                <li>text 2 one</li>
                <li>text 2 two</li>
                <li>text 2 three</li>
                <li>text 2 four</li>
            </ol>
            <li class="title">TITLE THREE</li>
            <ol class="foo">
                <li>text 3 one</li>
                <li>text 3 two</li>
                <li>text 3 three</li>
                <li>text 3 four</li>
            </ol>
        </ol>
    </body>
</html>

Wynik: http://i.stack.imgur.com/78bN8.jpg

KingRider
źródło
2

Mam pewien problem, gdy istnieją dwie listy, a druga znajduje się w DIV. Druga lista powinna zaczynać się od 1., a nie 2.1

<ol>
    <li>lorem</li>
    <li>lorem ipsum</li>
</ol>

<div>
    <ol>
        <li>lorem (should be 1.)</li>
        <li>lorem ipsum ( should be 2.)</li>
    </ol>
</div>

http://jsfiddle.net/3J4Bu/364/

EDYCJA: Rozwiązałem problem przez http://jsfiddle.net/hy5f6161/

robertad
źródło
1

W niedalekiej przyszłości możesz być w stanie użyć elementu ::markerpsuedo, aby osiągnąć ten sam rezultat, co inne rozwiązania w jednym wierszu kodu.

Pamiętaj, aby sprawdzić tabelę zgodności przeglądarki, ponieważ wciąż jest to technologia eksperymentalna. W chwili pisania tego tylko Firefox i Firefox dla Androida, począwszy od wersji 68, obsługują to.

Oto fragment kodu, który zostanie poprawnie wyrenderowany, jeśli zostanie wypróbowany w zgodnej przeglądarce:

::marker { content: counters(list-item,'.') ':' }
li { padding-left: 0.5em }
<ol>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
  <li>li element</li>
  <li>li element
    <ol>
      <li>sub li element</li>
      <li>sub li element</li>
      <li>sub li element</li>
    </ol>
  </li>
</ol>

Możesz także sprawdzić ten świetny artykuł, smashingmagazine na ten temat.

tyrion
źródło
0

Musiałem dodać to do rozwiązania opublikowanego w 12, ponieważ korzystałem z listy z mieszaniną listy uporządkowanej i list nieuporządkowanych. treść: brak ścisłego cytatu wydaje się dziwną rzeczą do dodania Wiem, ale działa ...

ol ul li:before {
    content: no-close-quote;
    counter-increment: none;
    display: list-item;
    margin-right: 100%;
    position: absolute;
    right: 10px;
}
Benjarlett
źródło
0

Dla mnie działało:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
}

ol > li {
  display: table;
  counter-increment: item;
  margin-bottom: 0.6em;
}

ol > li:before {
  content: counters(item, ".") ") ";
  display: table-cell;
  padding-right: 0.6em;
}

li ol > li {
  margin: 0;
}

li ol > li:before {
  content: counters(item, ".") ") ";
}

Spójrz na: http://jsfiddle.net/rLebz84u/2/

lub ten http://jsfiddle.net/rLebz84u/3/ z więcej i uzasadnionym tekstem

Willy Wonka
źródło
Strata czasu na spojrzenie. Prawie identyczny z wcześniejszą odpowiedzią. Jedyną różnicą jest „)” na końcu znacznika.
juanitogan
0

jest to poprawny kod, jeśli chcesz najpierw potomnie zmienić rozmiar innego css.

<style>
    li.title { 
        font-size: 20px; 

        counter-increment: ordem; 
        color:#0080B0;
    }
    .my_ol_class { 
        counter-reset: my_ol_class; 
        padding-left: 30px !important; 
    }
    .my_ol_class li { 
          display: block;
        position: relative;

    }
    .my_ol_class li:before { 
        counter-increment: my_ol_class; 
        content: counter(ordem) "." counter(my_ol_class) " "; 
        position: absolute;
        margin-right: 100%;
        right: 10px; /* space between number and text */
    }
    li.title ol li{
         font-size: 15px;
         color:#5E5E5E;
    }
</style>

w pliku HTML.

        <ol>
            <li class="title"> <p class="page-header list_title">Acceptance of Terms. </p>
                <ol class="my_ol_class">
                    <li> 
                        <p>
                            my text 1.
                        </p>
                    </li>
                    <li>
                        <p>
                            my text 2.
                        </p>
                    </li>
                </ol>
            </li>
        </ol>
Sandeep Kumar
źródło