21

The styling of nested lists with mixed or multiple child elements isn’t great. If you have only a single paragraph of text or a single nested list item within a parent list item then there’s no issue, but as soon as you have more than one child element the styling starts to get a bit unpredictable. This is most noticeable when you have nested lists along with paragraph text in the same parent list item, but also affects things like code blocks and quotes.

This has come up as a support issue (for example How to insert subitem into list without breaking layout? and Nested indenting issue).

The issue is the explicit lack of a bottom margin on child lists and paragraphs regardless of whether there are succeeding elements. So for example, this:

- List item

    - Child list item

    More list item text

- List item

Is rendered as:

  • List item

    • Child list item

    More list item text

  • List item

And as an image for posterity:

enter image description here

This is because the first "List item" text is wrapped in a <p> tag that has a bottom margin, whereas the child list item and "Child item text" has no bottom margin.

The offending CSS rules (found in "all.css") are:

ul ul, ol ul, ul ol, ol ol {
    margin-bottom: 0;
}

.post-text ul p:last-of-type,
.wmd-preview ul p:last-of-type,
.post-text ol p:last-of-type,
.wmd-preview ol p:last-of-type {
    margin-bottom: 0;
}

Now, we don’t want all nested lists to have no bottom margin and we don’t the last paragraph to have no bottom margin unless it is the last element in that list item, not just the last paragraph.

The simple solution is to remove both of those declarations and replace with:

ul :last-child, ol :last-child {
    margin-bottom: 0;
}

That gives us no bottom margin on the last child element of anything inside lists, which would also cover the last list item itself, meaning we could get rid of this (also in "all.css") too:

.post-text ul li:last-child,
.wmd-preview ul li:last-child,
.post-text ol li:last-child,
.wmd-preview ol li:last-child {
    margin-bottom: 0;
}

Just for reference, this is how the previous example looks with the improved CSS:

enter image description here

Maybe I’m overlooking some other case where those rules are important or maybe they're used elsewhere and simply removing them isn't the best option but at least change the rule affecting paragraphs from :last-of-type to :last-child and stop removing the bottom margin on all nested lists...

This is also a problem with non-nested lists when multiple paragraphs are used. This:

- List item

 Second paragraph for item

- List item

- List item

is rendered like this:

  • List item

    Second paragraph for item

  • List item

  • List item

as an image for posterity:

enter image description here

The second paragraph of the first item shouldn't be visually closer to the second item than it is to the preceding paragraph in the first item.

TL;DR Better nested list spacing please.

1

2 Answers 2

5

Oh hey, looks like we fixed this when switching over to the newfangled Stacks prose component for Markdown rendering.

3
+100

Until this is fixed properly via CSS, there is a work-around (with three variations).

In the following examples, &#x2003; is the em-space character and &#x25CF; is the black circle character (used because the bullet character &#x2022; is too small).


The first variation is closest to the improved CSS version. It uses manual line breaks and em-spaces to create the second level (and deeper) nested lists.

Raw:

- List item  
<br>&#x2003;&#x25CF; Child list item  

    More list item text

- List item

Display:

  • List item

     ● Child list item

    More list item text

  • List item


The second variation results in a dense list. It uses em-spaces at the start of, and normal double-spaces at the end of, each line to manually create the entire nested list.
(The double-space at the end could also be replaced by a <br> at the start.)

Raw:

&#x2003;&#x25CF; List item  
&#x2003;&#x2003;&#x2003;&#x25CF; Child list item  
&#x2003;&#x2003;More list item text  
&#x2003;&#x25CF; List item  

Display:

 ● List item
   ● Child list item
  More list item text
 ● List item


The third variation results in an evenly-spaced sparse list. It uses a leading manual line break, a trailing double-space, and em-spaces to manually create the entire nested list.
(Could also use an extra <br> at the start instead of the double-space at the end.)

Raw:

&#x2003;&#x25CF; List item  
<br>&#x2003;&#x2003;&#x2003;&#x25CF; Child list item  
<br>&#x2003;&#x2003;More list item text  
<br>&#x2003;&#x25CF; List item  

Display:

 ● List item

   ● Child list item

  More list item text

 ● List item

--------------------------------------------------------------------------------------------------------------

Using the example from this question to demonstrate how to deal with consecutive nested items and extra long lines:


With a double-space at the end of the 1. and 2. lines:

- **Variable name casing**: See [wikipedia article](https://en.wikipedia.org/wiki/Snake_case) on *"Snake Case"*. In Perl, we use *"snake_case"* instead of *"camelCase"*, and be consistent. Example:  
<br>&#x2003;1. Line 14: `my $testType`  
<br>&#x2003;2. Line 18: `my $right_frame`

    In the first line you use camelCase, whereas in the second you use snake_case.

- **Function name casing**:
  • Variable name casing: See wikipedia article on "Snake Case". In Perl, we use "snake_case" instead of "camelCase", and be consistent. Example:

     1. Line 14: my $testType

     2. Line 18: my $right_frame

    In the first line you use camelCase, whereas in the second you use snake_case.

  • Function name casing:


Removing the leading manual line breaks:

- **Variable name casing**: See [wikipedia article](https://en.wikipedia.org/wiki/Snake_case) on *"Snake Case"*. In Perl, we use *"snake_case"* instead of *"camelCase"*, and be consistent. Example:  
&#x2003;1. Line 14: `my $testType`  
&#x2003;2. Line 18: `my $right_frame`  

    In the first line you use camelCase, whereas in the second you use snake_case.

- **Function name casing**:
  • Variable name casing: See wikipedia article on "Snake Case". In Perl, we use "snake_case" instead of "camelCase", and be consistent. Example:

     1. Line 14: my $testType
     2. Line 18: my $right_frame

    In the first line you use camelCase, whereas in the second you use snake_case.

  • Function name casing:


The dense version (double-spaces at the end of every line):

&#x2003;&#x25CF; **Variable name casing**: See [wikipedia article](https://en.wikipedia.org/wiki/Snake_case) on *"Snake Case"*. In Perl, we use  
&#x2003;&#x2003;*"snake_case"* instead of *"camelCase"*, and be consistent. Example:  
&#x2003;&#x2003;&#x2003;1. Line 14: `my $testType`  
&#x2003;&#x2003;&#x2003;2. Line 18: `my $right_frame`  
&#x2003;&#x2003;In the first line you use camelCase, whereas in the second you use snake_case.  
&#x2003;&#x25CF; **Function name casing**:  

 ● Variable name casing: See wikipedia article on "Snake Case". In Perl, we use
  "snake_case" instead of "camelCase", and be consistent. Example:
   1. Line 14: my $testType
   2. Line 18: my $right_frame
  In the first line you use camelCase, whereas in the second you use snake_case.
 ● Function name casing:

--------------------------------------------------------------------------------------------------------------

In answer to fgrieu's question from this post regarding how to correctly use bullets and how to handle long lines:

1. **Mammals**

 like:
<br>&nbsp; &nbsp; &#x25CF; cat multidisciplinary study including sedimentologic, stratigraphic, isotopic,
<br>&#x2003;&#x2003;and palynological aspects in order to reconstruct the paleoenvironment
<br>&#x2003;&#x2003;and to evaluate biochronologic and paleogeographic implications.
<br>&nbsp; &nbsp; &#x25CF; cow
<br>&nbsp; &nbsp; &#x25CF; dog
<br>New faunal and stratigraphic evidence documents the validity of the North American Clarkforkian.

2. **Smurf**
  1. Mammals

    like:
        ● cat multidisciplinary study including sedimentologic, stratigraphic, isotopic,
      and palynological aspects in order to reconstruct the paleoenvironment
      and to evaluate biochronologic and paleogeographic implications.
        ● cow
        ● dog
    New faunal and stratigraphic evidence documents the validity of the North American Clarkforkian.

  2. Smurf

Note the missing space in front of New faunal. It is not required, but doesn't affect the result if included.
Also note the different usages of '&nbsp; &nbsp; &#x25CF; ' (trailing space) and '&#x2003;&#x2003;' (no trailing space). These, and all the spaces in them, are critical for correct alignment.


Caveat: Tested and working correctly on Firefox ESR 52.3.0

9
  • 4
    While the workaround is interesting, IMO it's best not to use it. Not only does it make the markdown harder to read, it also generates semantically incorrect HTML, which can negatively impact screen readers, etc..
    – Bob
    Commented Sep 21, 2017 at 5:45
  • 1
    @Bob: I very much hesitate to use that heroic workaround and run the risk of incompatibility with some browsers. Plus in my actual use case, I'm running into the 30000 character limits in the markdown for an answer! The real answer is: the powers that be do the right thing and fix the CSS or whatever it takes!
    – fgrieu
    Commented Sep 21, 2017 at 6:01
  • 2
    Faking indentation with manual line breaks and spaces isn't a good idea. It breaks on mobile (and on desktop with any change to font or font-size).
    – Cai
    Commented Sep 21, 2017 at 8:12
  • @Cai I did think there might be issues on mobile devices. However, I just tested on an iPad using Safari 7.1 and Puffin Browser, and on an iPhone 6 with Safari. Also changed default font and size in Firefox. Apart from a minor long line glitch on the iPad and the iPhone in landscape orientation, the only major issue is long lines on the iPhone in portrait mode (as expected). Other than long lines, do you have any specific info on exactly what breaks in which browsers?
    – robinCTS
    Commented Sep 21, 2017 at 9:59
  • I assume what you say is a "minor long line glitch" is what I mean by broken.
    – Cai
    Commented Sep 21, 2017 at 10:01
  • @Cai Minor glitch fixed :P Just a matter of learning how long to leave lines before manually breaking them ;) Seriously, though, I agree with you that it's probably not a good idea manually break long/mid-length lines.
    – robinCTS
    Commented Sep 21, 2017 at 10:17
  • @Bob I agree with you about the markdown being harder to read. However, I had a look at the HTML and it seems correct to me. Can you be a bit more specific what is wrong with it?
    – robinCTS
    Commented Sep 21, 2017 at 10:25
  • 1
    @robinCTS Semantic HTML means your HTML tags are supposed to describe the actual data. When you pull tricks like this, you end up with a <p>item1<br><br>item2</p>, which is semantically incorrect - it's actually supposed to be <li>item1</li><li>item2</li>. Semantic HTML can be seen as a kind of "standard" to better support atypical display methods, e.g. a screen reader might navigate two <li> differently to a single <p>, a crawler (like Google) might parse <li> into one of those info boxes, etc.
    – Bob
    Commented Sep 21, 2017 at 10:34
  • 4
    Your HTML is syntactically correct/valid, in that it won't throw any parsing errors. It's semantically wrong because it doesn't use the tags with the correct meaning for the data.
    – Bob
    Commented Sep 21, 2017 at 10:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .