简体   繁体   中英

Prevent list item text wrapping under item when using :before to increment counter with sub lists

I have a simple ordered list that has some list items and within those may be a sub list. I want to increment the number of the list item to the child / sub ordered lists so the layout is like so:

1. Blah blah blah
2. Yeah yeah yeah
3. Jadda jadda jadda
3.1 Sub jadda
3.2 Sub Jadda

This isn't so hard to do, my code does this (have a look at the code snippet)...

 .container { background-color: #c7e8f7; border: 1px solid #00bcd4; width:800px; padding: 5px; } ol { counter-reset: item; list-style-type: none; padding-left: 0px; } li:before { content: counters(item, ".") "."; counter-increment: item; } /* Add an indent to the sub ol*/ ol ol { padding-left: 10px; }
 <div class="container"> <ol> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li> here is some text... <ol> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> </ol> </li> </ol> </div>

Now the problem is that my text wraps under the list item number, I don't want this, I want the number to have a column (like it would be if I wasn't using the :before to set the increment number). My uploaded image shows how the content wraps below the number. Does anyone know of a way without modifying the HTML structure (CSS only) to prevent the wrap?

Please note, if I haven't described my problem clearly please say so and I shall reword the question - many thanks.

在此处输入图片说明

This can be done by making use of display: table property on the list. Then apply display: table-cell on li:before in order to provide indent on the second line and so on. display: table-row on li in order to have li text in the same row as the table-cell .

Additions to CSS

ol{
  display: table;
}

li:before {
  display: table-cell;
}

li {
  display: table-row;
  // Add spacing to left as per requirement.
}

SNIPPET

 .container { background-color: #c7e8f7; border: 1px solid #00bcd4; width: 800px; padding: 5px; } ol { counter-reset: item; list-style-type: none; padding-left: 0px; display: table; } li { display: table-row; } li:before { content: counters(item, ".") "."; counter-increment: item; display: table-cell; } /* Add an indent to the sub ol*/ ol ol { padding-left: 10px; }
 <div class="container"> <ol> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li> here is some text... <ol> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> </ol> </li> </ol> </div>

One approach is to provide a specific padding to the left of the <li> elements, and then position the generated ::before pseudo-element in that space:

/* This block is just to remove default padding
   and margin, and also to more easily assign
   width/height to elements: */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.container {
  background-color: #c7e8f7;
  border: 1px solid #00bcd4;
  width: 800px;
  padding: 5px;
}
ol {
  counter-reset: item;
  list-style-type: none;
}
li {
  /* padding the left of the <li>
     elements with 2em of 'empty space': */
  padding-left: 2em;
  /* setting the position to a non-'static'
     value, in order to position the
     pseudo-elements in relation to their
     closest <li>: */
  position: relative;
}
li:before {
  content: counters(item, ".")".";
  counter-increment: item;
  /* absolute positioning to remove the
     pseudo-element from the document
     flow, and to explicitly move them
     to the left-most edge: */
  position: absolute;
  left: 0;
}

 *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } .container { background-color: #c7e8f7; border: 1px solid #00bcd4; width: 800px; padding: 5px; } ol { counter-reset: item; list-style-type: none; padding-left: 0px; } li { padding-left: 2em; position: relative; } li:before { content: counters(item, ".")"."; counter-increment: item; position: absolute; left: 0; }
 <div class="container"> <ol> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis, interdum libero non, tincidunt dolor. Quisque vestibulum vitae augue eu tempus. Suspendisse nec enim mollis, auctor mi vitae, tincidunt lectus. Nullam interdum nisi at elit pretium, in tempus elit pharetra. Etiam posuere tempor sapien. Mauris pretium augue sapien, id vestibulum elit scelerisque a. Sed condimentum ligula mauris, in posuere metus ultricies eu. Quisque ac sem ut mauris finibus porta. Etiam sit amet aliquam odio, eu interdum tortor. Etiam ac porttitor nunc, quis elementum diam. Morbi nec vestibulum quam. Proin ultricies tempus tellus sit amet ultrices. Cras quam dolor, vestibulum non quam ut, rutrum tincidunt augue. Vestibulum et nisl elit.</li> <li>here is some text... <ol> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> <li>orem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas fringilla tellus purus, quis convallis odio accumsan at. Pellentesque non sagittis risus. Morbi in nulla lobortis</li> </ol> </li> </ol> </div>

The main problem with this approach, of course, is the arbitrary means of assigning the 'column'-width of the pseudo-elements, depending on how involved your list gets it's potentially possible to get to a state where 2em isn't sufficient to contain the list-item number of 1.4.2.4.baiii ; so this may be a fragile solution. Although you could, explicitly style those elements with:

li li li li li li li::before {
    position: static;
    display: block;
}

To place the counter above the content of those elements (or do whatever else might better suit your design constraints).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM