A lista ordenada pode produzir resultados parecidos com 1.1, 1.2, 1.3 (em vez de apenas 1, 2, 3,…) com css?

201

Uma lista ordenada pode produzir resultados parecidos com 1.1, 1.2, 1.3 (em vez de apenas 1, 2, 3, ...) com CSS? Até agora, o uso list-style-type:decimalproduziu apenas 1, 2, 3, e não 1.1, 1.2., 1.3.

Richard77
fonte
Sugiro comparar a resposta aceita com a de Jakub Jirutka. Eu acho que o último é ainda melhor.
Frank Conijn
Solução elegante. Alguma idéia de por que a Wikipedia usa um ul para suas seções de conteúdo em vez disso?
Mattypants
1
@davnicwil Eu concordo; parece que provavelmente apliquei a duplicata na ordem errada em setembro.
TylerH
Legal, agora me sinto estranho porque nunca me ocorreu que poderia ser um erro simples assim - desculpas!
Davnicwil 17/07/19

Respostas:

289

Você pode usar contadores para fazer isso:

Os seguintes números de folha de estilo aninham itens da lista como "1", "1.1", "1.1.1" etc.

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

Exemplo

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>

Consulte Contadores e escopo aninhados para obter mais informações.

quiabo
fonte
2
Ótima resposta. Qual é o suporte para isso?
Jason McCreary
1
@ Jason McCreary: Bem, esse é o lado negativo: os contadores não são suportados no IE até a versão 8 .
Gumbo #
3
Esta solução perde uma pequena coisa: o ponto após o número do item. Não se parece com o estilo de lista padrão. Corrija adicionando um ponto à regra para li:before: content: counters(item, ".")". ";
LS
4
Esta é uma resposta ruim. Não funciona corretamente. Confira a resposta de Jakub Jirutka abaixo
Mr Pablo
1
@ Gumbo eu sei, e a resposta de Jakub me deu a numeração correta.
Pablo Pablo
236

Nenhuma das soluções desta página funciona correta e universalmente para todos os níveis e parágrafos longos (agrupados). É realmente complicado conseguir um recuo consistente devido ao tamanho variável do marcador (1., 1.2, 1.10, 1.10.5, ...); não pode ser apenas "falsificado", nem mesmo com uma margem / preenchimento pré-computado para cada nível de indentação possível.

Finalmente, descobri uma solução que realmente funciona e não precisa de JavaScript.

Foi testado no Firefox 32, Chromium 37, IE 9 e Android Browser. Não funciona no IE 7 e anterior.

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, ".") " ";
}

Exemplo: Exemplo

Experimente no JSFiddle , bifurque no Gist .

Jakub Jirutka
fonte
1
Bom trabalho alcançando esse tipo de indentação. Eu ainda argumentaria, no entanto, que os dois primeiros casos de indentação que você listou são uma questão de preferência, e não certo e errado. Considere o caso 1 e o caso 2 - o último consegue espremer muito mais níveis antes que o espaçamento se torne pesado, enquanto ainda parece bem arrumado. Além disso, o MS Word e o estilo padrão do navegador usam recuo do caso 2. Eu acho que eles também estão fazendo errado?
Saul Fautley
2
@ Saul-Fautley É errado em termos de tipografia. Seu exemplo com número insano de níveis aninhados demonstra que a numeração aninhada não é adequada para muitos níveis, mas isso é bastante óbvio. O MS Words não é um sistema tipográfico, é um mero processador de documentos com tipografia ruim. Estilo padrão do navegador ... oh, você não sabe muito sobre tipografia, sabe?
Jakub Jirutka
3
Realmente funciona (tecnicamente) para todos os níveis e parágrafos longos. Se for razoável usar uma dúzia de níveis, essa é outra questão que não tem nada a ver com a solução técnica. O ponto é que você não precisa predefinir uma regra CSS para cada nível de aninhamento, como ocorre com algumas outras soluções.
Jakub Jirutka
4
Enquanto eu não diria que há algo inerentemente "errado" com as outras respostas, eu diria que elas estão incompletas. Essa resposta é imediata e até funcionou em um site horrivelmente bizarramente estilizado que estou alterando.
30515 DanielM
2
@ tremby: A discrepância pode ser resolvida fazendo com que o li use "display: table-row" em vez de "display: table". O problema que isso traz é que o li não pode usar margens / preenchimentos, pois as linhas da tabela sempre são dimensionadas automaticamente pelo seu conteúdo. Para solucionar esse problema, adicione um "li: after" com "display: block". Veja jsFiddle para um exemplo completo. Como um bônus extra, adicionei "text-align: right" a "li: before" para tornar os números alinhados à direita.
mmlr
64

A resposta escolhida é um ótimo começo, mas essencialmente força o list-style-position: inside;estilo nos itens da lista, dificultando a leitura do texto agrupado. Aqui está uma solução simples que também fornece controle sobre a margem entre o número e o texto e alinha o número à direita conforme o comportamento padrão.

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
fonte
Uma desvantagem é que ele adiciona um ponto final ao final de cada item da lista.
Davin Studer
3
@Davin Studer: Ele adiciona apenas um ponto ao final de cada número, conforme o olcomportamento padrão . Ele pode ser facilmente removido excluindo o último "."da contentpropriedade, mas isso me parece um pouco estranho.
Saul Fautley 12/08
14

As soluções postadas aqui não funcionaram bem para mim, então fiz uma mistura das perguntas desta pergunta e da seguinte: É possível criar uma lista ordenada em vários níveis em 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 */

Resultado:

captura de tela

Nota: a captura de tela, se você deseja ver o código-fonte ou o que for deste post: http://estiloasertivo.blogspot.com.es/2014/08/introduccion-running-lean-y-lean.html

chelder
fonte
1
Esta é a melhor (e mais simples) resposta de trabalho de toda a página.
Bruno Toffolo
6

Nota: Use CSS para criar numeração aninhada em um navegador moderno. Veja a resposta aceita. O seguinte é apenas para interesse histórico.counters


Se o navegador suportar contente 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
fonte
Esta solução falha terrivelmente quando as listas são aninhadas.
LS
@LS Você sempre pode acomodar os seletores para atender às suas necessidades. .foo > ol > li.
precisa saber é
1
O que quero dizer é que você codificou "1". no estilo. O que acontece quando a sublist é filha do segundo item da lista pai? Você deseja que apareça como "2.", mas sempre será "1". por causa da maneira como é codificado aqui. Qual a solução? Faça novos conjuntos de estilos para cada número possível? Não. Use a counters()função como nos exemplos acima, em vez da counter()função.
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>

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

KingRider
fonte
2

Eu tenho algum problema quando há duas listas e a segunda está dentro do DIV. A segunda lista deve começar em 1. não 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/

EDIT: Eu resolvi o problema por este http://jsfiddle.net/hy5f6161/

robertad
fonte
1

Em um futuro próximo, você poderá usar o ::markerelemento psuedo para obter o mesmo resultado que outras soluções em apenas uma linha de código.

Lembre-se de verificar a tabela de compatibilidade do navegador pois essa ainda é uma tecnologia experimental. No momento da gravação, apenas o Firefox e o Firefox para Android, a partir da versão 68, suportam isso.

Aqui está um trecho que será renderizado corretamente se tentado em um navegador compatível:

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

Você também pode conferir este ótimo artigo por smashingmagazine sobre o assunto.

tyrion
fonte
0

Eu precisava adicionar isso à solução publicada em 12, pois estava usando uma lista com uma mistura de componentes de lista ordenada e listas não ordenadas. content: no-close-quote parece uma coisa estranha a acrescentar, eu sei, mas funciona ...

ol ul li:before {
    content: no-close-quote;
    counter-increment: none;
    display: list-item;
    margin-right: 100%;
    position: absolute;
    right: 10px;
}
benjarlett
fonte
0

O seguinte funcionou para mim:

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, ".") ") ";
}

Veja: http://jsfiddle.net/rLebz84u/2/

ou este http://jsfiddle.net/rLebz84u/3/ com mais texto justificado

Willy Wonka
fonte
Perda de tempo para olhar. Quase idêntico a uma resposta anterior. A única diferença é ")" foi adicionada ao final do marcador.
juanitogan
0

esse é um código adequado se você deseja redimensionar o primeiro filho de outro 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>

no arquivo 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
fonte