รายการที่เรียงลำดับสามารถสร้างผลลัพธ์ที่ดูเหมือน 1.1, 1.2, 1.3 (แทนที่จะเป็นเพียง 1, 2, 3, …) ด้วย css หรือไม่


201

รายการที่เรียงลำดับสามารถสร้างผลลัพธ์ที่มีลักษณะเช่น 1.1, 1.2, 1.3 (แทนที่จะเป็นเพียง 1, 2, 3, ... ) ด้วย CSS หรือไม่? จนถึงตอนนี้การใช้list-style-type:decimalมีการผลิตเพียง 1, 2, 3, ไม่ใช่ 1.1, 1.2., 1.3


ฉันขอแนะนำให้เปรียบเทียบคำตอบที่ได้รับการยอมรับโดย Jakub Jirutka ฉันคิดว่าดีกว่านี้มาก
Frank Conijn

ทางออกที่สง่างาม ความคิดใดที่ว่าทำไม Wikipedia ใช้ ul สำหรับส่วนเนื้อหาแทนที่จะเป็นสิ่งนี้
Mattypants

1
@davnicwil ฉันเห็นด้วย ดูเหมือนว่าฉันอาจใช้ซ้ำในลำดับที่ผิดกลับมาในเดือนกันยายน
TylerH

เยี่ยมยอดตอนนี้ฉันรู้สึกอึดอัดใจเพราะมันไม่เคยเกิดขึ้นกับฉันเลยมันอาจจะเป็นข้อผิดพลาดง่ายๆแบบนั้น - ขอโทษ!
davnicwil

คำตอบ:


289

คุณสามารถใช้เคาน์เตอร์เพื่อทำสิ่งต่อไปนี้:

หมายเลขสไตล์ชีตต่อไปนี้แสดงเป็นรายการแบบซ้อน "1", "1.1", "1.1.1" เป็นต้น

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

ตัวอย่าง

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>

ดูตัวนับและขอบเขตแบบซ้อนสำหรับข้อมูลเพิ่มเติม


2
คำตอบที่ดี การสนับสนุนสำหรับสิ่งนี้คืออะไร?
Jason McCreary


3
วิธีการแก้ปัญหานี้หายไปหนึ่งสิ่งเล็ก ๆ : จุดที่ตามหมายเลขรายการ มันดูไม่เหมือนสไตล์รายการมาตรฐาน แก้ไขโดยการเพิ่มจุดไปยังกฎสำหรับli:before: content: counters(item, ".")". ";
LS

4
นี่เป็นคำตอบที่ไม่ดี มันทำงานไม่ถูกต้อง ตรวจสอบคำตอบโดย Jakub Jirutka ด้านล่าง
Mr Pablo

1
@Gumbo ฉันรู้และคำตอบโดย Jakub ให้ฉันหมายเลขที่ถูกต้อง
นาย Pablo

236

ไม่มีวิธีแก้ไขปัญหาใด ๆ ในหน้านี้ที่ทำงานได้อย่างถูกต้องและเป็นสากลสำหรับทุกระดับและย่อหน้า (ยาว) เป็นการยากที่จะบรรลุการเยื้องที่สอดคล้องกันเนื่องจากขนาดตัวแปรของเครื่องหมาย (1. , 1.2, 1.10, 1.10.5, …); ไม่สามารถเป็นเพียง“ แกล้ง” ไม่ได้แม้แต่กับมาร์จิ้น / ช่องว่างที่คำนวณล่วงหน้าสำหรับแต่ละระดับการเยื้องที่เป็นไปได้

ในที่สุดฉันก็พบโซลูชันที่ใช้งานได้จริงและไม่ต้องการ JavaScript ใด ๆ

ผ่านการทดสอบบน Firefox 32, Chromium 37, IE 9 และเบราว์เซอร์ Android ไม่ทำงานบน IE 7 และรุ่นก่อนหน้า

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

ตัวอย่าง: ตัวอย่าง

ลองบนJSFiddle , แยกบนสรุปสาระสำคัญ


1
งานที่ดีบรรลุการเยื้องประเภทนี้ ฉันจะยังคงยืนยันว่าการเยื้องสองกรณีแรกที่คุณระบุไว้นั้นเป็นเรื่องของการตั้งค่ามากกว่าถูกและผิด พิจารณากรณีที่ 1และกรณีที่ 2 - คนหลังจัดการบีบในระดับมากขึ้นก่อนระยะห่างกลายเป็นเทอะทะในขณะที่ยังดูเรียบร้อยสวย นอกจากนี้ MS Word และสไตล์เบราว์เซอร์เริ่มต้นยังใช้การเยื้องของกรณีที่ 2 ฉันเดาว่าพวกเขาทำผิดเช่นกัน?
Saul Fautley

2
@ saul-fautley มันผิดในแง่ของการพิมพ์ ตัวอย่างของคุณที่มีระดับที่ซ้อนกันจำนวนบ้าแสดงให้เห็นว่าการกำหนดหมายเลขแบบซ้อนไม่เหมาะสำหรับหลาย ๆ ระดับ แต่ก็ค่อนข้างชัดเจน MS Words ไม่ใช่ระบบเรียงพิมพ์มันเป็นเพียงตัวประมวลผลเอกสารที่มีตัวอักษรไม่ดี เบราว์เซอร์เริ่มต้นจัดแต่งทรงผม…โอ้คุณไม่ค่อยรู้เรื่องการพิมพ์ใช่ไหม
Jakub Jirutka

3
มันใช้งานได้จริง (ทางเทคนิค) สำหรับทุกระดับและย่อหน้ายาว ๆ ถ้ามันสมเหตุสมผลที่จะใช้ระดับโหลนั่นเป็นอีกคำถามหนึ่งที่ไม่มีส่วนเกี่ยวข้องกับโซลูชันทางเทคนิค ประเด็นก็คือคุณไม่จำเป็นต้องกำหนดกฎ CSS ล่วงหน้าสำหรับแต่ละระดับการซ้อนเช่นเดียวกับโซลูชันอื่น ๆ
Jakub Jirutka

4
ในขณะที่ฉันจะไม่พูดว่ามีอะไร "ผิด" โดยธรรมชาติกับคำตอบอื่น ๆ ฉันจะบอกว่าพวกเขาไม่สมบูรณ์ คำตอบนี้เป็นจุดที่และแม้กระทั่งทำงานในเว็บไซต์ที่มีสไตล์แปลกประหลาดที่ฉันแก้ไข
DanielM

2
@tremby: ความคลาดเคลื่อนสามารถแก้ไขได้โดยทำให้ li ใช้ "display: table-row" แทน "display: table" ปัญหาที่เกิดขึ้นคือ li นั้นไม่สามารถใช้ระยะขอบ / ช่องว่างภายในเนื่องจากแถวของตารางจะถูกปรับขนาดโดยอัตโนมัติตามเนื้อหาของพวกเขา สามารถแก้ไขได้โดยเพิ่ม "li: after" กับ "display: block" ดูjsFiddleสำหรับตัวอย่างเต็มรูปแบบ ในฐานะโบนัสพิเศษฉันเพิ่ม "การจัดแนวข้อความ: ขวา" ถึง "li: ก่อน" เพื่อให้จัดแนวขวา
mmlr

64

คำตอบที่เลือกเป็นการเริ่มต้นที่ดี แต่มันบังคับให้list-style-position: inside;สไตล์ในรายการเป็นหลักทำให้การห่อข้อความยากที่จะอ่าน ต่อไปนี้เป็นวิธีแก้ไขปัญหาอย่างง่ายที่ให้การควบคุมระยะห่างระหว่างหมายเลขและข้อความและจัดชิดหมายเลขตามพฤติกรรมเริ่มต้น

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/


หนึ่งข้อเสียคือมันเพิ่มระยะเวลาในตอนท้ายของแต่ละรายการ
Davin Studer

3
@Davin Studer: มันจะเพิ่มช่วงเวลาไปยังจุดสิ้นสุดของแต่ละหมายเลขเท่านั้นตามolพฤติกรรมเริ่มต้น สามารถลบออกได้อย่างง่ายดายโดยการลบรายการสุดท้าย"."จากcontentสถานที่ แต่นี่ดูแปลกสำหรับฉัน
Saul Fautley

14

โซลูชันที่โพสต์ที่นี่ทำงานได้ไม่ดีสำหรับฉันดังนั้นฉันจึงผสมผสานคำถามเหล่านี้กับคำถามต่อไปนี้: เป็นไปได้ไหมที่จะสร้างรายการที่เรียงลำดับหลายระดับใน 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 */

ผลลัพธ์:

ภาพหน้าจอ

หมายเหตุ: ภาพหน้าจอหากคุณต้องการดูซอร์สโค้ดหรืออะไรก็ตามที่อยู่ในโพสต์นี้: http://estiloasertivo.blogspot.com.es/2014/08/introduccion-running-lean-y-lean.html


1
นี่คือคำตอบที่ใช้งานได้ดีที่สุด (และง่ายที่สุด) จากทั้งหน้า
Bruno Toffolo

6

หมายเหตุ: ใช้ CSS เพื่อสร้างการกำหนดหมายเลขแบบซ้อนในเบราว์เซอร์สมัยใหม่ ดูคำตอบที่ยอมรับได้ ต่อไปนี้เป็นเพื่อประโยชน์ทางประวัติศาสตร์เท่านั้นcounters


หากเบราว์เซอร์สนับสนุนcontentและ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>


การแก้ปัญหานี้ล้มเหลวอย่างน่ากลัวเมื่อรายการซ้อนกัน
LS

@LS คุณสามารถเลือกเครื่องมือให้เหมาะกับความต้องการของคุณได้เสมอ .foo > ol > li.
kennytm

1
ประเด็นของฉันคือคุณได้เขียนโค้ดยาก "1. " เป็นสไตล์ จะเกิดอะไรขึ้นเมื่อรายการย่อยเป็นรายการย่อยของรายการที่สองในรายการหลัก คุณต้องการให้มันปรากฏเป็น "2. " แต่มันจะเป็น "1. " เสมอ เพราะวิธีที่มันเขียนไว้ที่นี่ ทางออกคืออะไร? สร้างชุดรูปแบบใหม่สำหรับทุกหมายเลขที่เป็นไปได้หรือไม่ ไม่ใช้counters()ฟังก์ชันตามตัวอย่างด้านบนแทนcounter()ฟังก์ชั่น
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>

ผลลัพธ์: http://i.stack.imgur.com/78bN8.jpg


2

ฉันมีปัญหาบางอย่างเมื่อมีสองรายการและรายการที่สองอยู่ใน DIV รายการที่สองควรเริ่มต้นที่ 1 ไม่ใช่ 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/

แก้ไข: ฉันแก้ไขปัญหาโดยhttp://jsfiddle.net/hy5f6161/นี้


1

ในอนาคตอันใกล้นี้คุณอาจจะสามารถใช้::markerองค์ประกอบ psuedoเพื่อให้ได้ผลลัพธ์เช่นเดียวกับโซลูชันอื่น ๆ ในรหัสบรรทัดเดียว

อย่าลืมตรวจสอบตารางความเข้ากันได้ของเบราว์เซอร์เนื่องจากยังคงเป็นเทคโนโลยีทดลอง ในขณะที่เขียนเท่านั้น Firefox และ Firefox สำหรับ Android เริ่มจากรุ่น 68 สนับสนุนนี้

นี่เป็นตัวอย่างข้อมูลที่จะแสดงผลอย่างถูกต้องหากลองใช้เบราว์เซอร์ที่ใช้งานร่วมกันได้:

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

คุณอาจต้องการตรวจสอบบทความที่ดีนี้โดย smashingmagazineในหัวข้อ


0

ฉันต้องการเพิ่มสิ่งนี้ลงในโซลูชันที่โพสต์ใน 12 เนื่องจากฉันใช้รายการที่มีส่วนผสมของรายการที่สั่งซื้อและส่วนประกอบรายการที่ไม่มีการเรียงลำดับ เนื้อหา: no-close-quote ดูเหมือนจะเป็นเรื่องแปลกที่ฉันจะเพิ่ม แต่มันใช้งานได้ ...

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

0

การทำงานต่อไปนี้สำหรับฉัน:

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

ดูที่: http://jsfiddle.net/rLebz84u/2/

หรือhttp://jsfiddle.net/rLebz84u/3/อันนี้ พร้อมข้อความที่ถูกต้อง


เสียเวลาดู เกือบเหมือนคำตอบก่อนหน้านี้ เพิ่มความแตกต่างเพียงอย่างเดียวคือ ")" ต่อท้ายเครื่องหมายแล้ว
juanitogan

0

นี่คือรหัสที่ถูกต้องถ้าคุณต้องการลูกคนแรก li ปรับขนาดของ 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>

ในไฟล์ 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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.