Minimize Spacing Between Inlined LIs?

This is definitely a worthy tip for developers to know.

I think we may have been a bit too hasty :slight_smile:

It seems to work everywhere apart from Safari (and IOS) which are still overlapping when using the negative letter spacing. That means that if the measurements aren’t exact you get small overlap so you can’t use -99em etc. If you use -1ex it seems to work ok but does overlap slightly.

1 Like

Bummer. It looked so good, like its time had finally come.

1 Like

Arrgh, one misbehaving browser and it starts to get dirty! So it seems that the letter spacing value has to be exact, which I can’t think can be guaranteed but we can get close enough. Hopefully, I think this can be combined with the font-size: 0 technique:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Remove white space between inline-block tags</title>
<style type="text/css">
body {
    background: #ccc;
}
ul {
    font-size: 0;
    font-family: 'courier new', monospace;
    letter-spacing: -0.6em; /* fallback when font-size: 0 doesn't work */
}
li {
    display: inline-block;
    letter-spacing: 0;
    font-size: 1rem;
}

li a {
    padding: .5em 1em;
    color: #FFF;
    background: #000;
    border: 1px solid blue;
    line-height: 2.2em;
}
li a:hover {
    background: red;
}
</style>
</head>
<body>
    <h1>Remove white space between inline-block tags</h1>
    <pre>
      By using negative font-size: 0 and letter-spacing on parent node.
    </pre>
    <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">Tutorials</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
    </ul>
</body>
</html>

In this case the letter spacing will be used only in cases when zero font size doesn’t work in IE with accessibility settings. It is only a fallback technique since in almost all cases the zero font size will work and then the letter spacing will be irrelevant. I set the monospace font so that the fallback is still as consistent as possible. From my tests even if you remove font-size: 0 this will work in all browsers since -0.6em appears to be the correct space size for a monospace font.

The downside it that we have to reset the font size instead of using a relative one (maybe someone knows a workaround for this?). Unfortunately, the simple letter spacing technique looked too good to be true.

So how does this version work in your tests?

Just going to bed I’ll check tomorrow :slight_smile:

That seems to work ok is safari and ios and other browsers however I am concerned with the magic number of .6em. A fraction either way and the gap re-appears which suggests to me that in some cases there could be rounding errors but as this is a fallback then I guess it’s not overly important. (Note that your anchors need display:block to work or the vertical padding you added will not take full effect.)

However, the fix is now more complicated than the original display:table-fix which has better support and works back to IE8 without any magic numbers (more or less) or special fonts or messing with font-size.

The original used word-spacing instead of letter-spacing but we can still use letter-spacing although there is no difference to the effect.

ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display:table;/* safari fix*/
}

ul {
  letter-spacing: -99em;
  /* inline-block white-space fix*/
}
li {
  display: inline-block;
  letter-spacing: normal;
  /* reset letter-spacing to normal becaus of inline-block white-space fix*/
}

All you need is the display:table on the ul which cures all webkit, safari and ios and then the negative letter spacing (or word-spacing) reduces the gap in all other modern browsers (webkit ignores word-spacing when display:table is used so it never overlaps).

I put a codepen up here:

As I mentioned in a subsequent post I was a little silly to say this was foolproof as there is no such thing and indeed it may not be future-proof if other browsers change their behavior with how letter or word-spacing is handled when inside a display:table element.

However the solution has already worked for several years which is probably more than could be hoped for for any hack :slight_smile:

In the end I think the font-size:0 and letter-spacing is also a pretty good candidate but has less older browser support than the display:table method.

I appreciate the effort you put into this and maybe there still is a perfect fix hiding in there somewhere.

@toad78 sorry to take over your thread a little but the title was about minimising space between inlined lists and that is exactly what we have been talking about :slight_smile:

3 Likes

[quote=“PaulOB, post:46, topic:238180”]
The original used word-spacing instead of letter-spacing but we can still use letter-spacing although there is no difference to the effect.
[/quote]I can be mistaken, but the original method using word-spacing appeared to not affect the children at all so the word-spacing reset wasn’t necessary?

Please correct me if I’m wrong.

I’m sure Paul will be along shortly, but… word spacing is inherited, so, yes, it does affect the children, thus the reset is necessary.

1 Like

Thank you very much!

Of course it is, I stand corrected.

2 Likes

The real solution seems to be on it’s way in CSS Module Level 4 with the text-space-collapse property.

That looks like it would go on the parent element like this…


ul {
    margin: 0;
    padding: 0;
    list-style: none;
    text-space-collapse: discard;
}

I believe this was supposed to be in CSS3 but was moved to level 4.

3 Likes

So that’s where it went :slight_smile:

I knew there was a spec in css3 but assumed it had been discarded. It was here but its not in latest draft.

Of course, the fix has now become more complicated than the original display-table fix, however it is not 100% equivalent - display: table has some side effects like no text-align and some other differences with how tables are handled as opposed to block and inline-block elements (I’m sure any of those side effects can be worked around). Even letter-spacing: -99em (or whatever other value) alone is a hack since there is no documentation saying what happens when the negative value exceeds the letter width so what Safari does may as well be fully compatible with the specs that only say that

Values may be negative, but there may be implementation-specific limits.

These are all hacks that rely on some magic or undocumented browser behaviours. 0.6em is a magic number (however, only used as an extremely rare fallback) but the way that display: table fixes Safari is also magical and that browser is free to change it in the future whenever it likes. The only true solution is the new CSS4 property that has been mentioned in this thread - or simply getting rid of the spaces in HTML :smiley: .

Of course, it’s always good to have different solutions to choose from!

2 Likes

Yes of course, I agree with most of what you say and you make good points.:slight_smile:

I just feel the display:table solution has been working well for several years and would be my preferred choice still taking into account the alternatives. There is of course no guarantee but that holds true for valid code also (as early flexboxers found out to their peril when the specs changed mid way - not to mention border-radius which changed specs midway also).

I think the mix of font-siz:0 and the negative letter spacing is also a good fix for now especially now that rems are supported and the inheritance problem are not so much of an issue.

Actually there are no adverse side effects to the text-alignment in the display:table-version and everything is as stylable as it was before (if not more so as display:table has some good benefits such as centering items without the need for a width). Indeed the display:table is a valid solution as the specs state that white-space between inner table elements should be collapsed. This follows the specs although only webkit is supporting it.

In the end you make your choice and do the best that you think suits the job in hand. There never really is one right answer in CSS as we often find out.

Thanks for taking the time to investigate this further (and Ray and others also) as it is only by constantly testing and proving/disproving that we learn how things really work and I’m always delighted when I learn something new or find a new way to do something I hadn’t thought possible :slight_smile:

Yes, I wouldn’t hold your breath on that one. Its been in and out like a yoyo :wink:

Yes, that was always the easiest solution if you controlled the mark up fully.

If however you hand the code to a client then it would not be a safe fix as simply loading it into an editor will lose the formatting (as I set mine to auto format). I feel that creating a presentation from your markup is intrinsically wrong and not something I would ever do. But of course I may be wrong :wink:

2 Likes

Sorry, you may be right, I forgot to set width: 100% to the table-like element before trying text-align, which didn’t obviously work in that setup.

You are right in your conclusions. I should have clarified it better when I said getting rid of spaces in HTML is the true solution - it is true in the sense that it is one without any hacks where browsers do exactly what they should be doing without any ambiguity. This solution is not true in the sense of providing separation of markup from css, which we strive for - so in the end it is not the ultimate solution that would satisfy us all :smiley:

When we are at the subject of markup and spaces I think that there are cases where white space may and should matter - not from the stylistic but semantic point of view. When we have list or block elements then I think white space does not matter:

<li>one</li>
<li>two</li>
<li>three</li>

<li>one</li><li>two</li><li>three</li>

<div>one</div>
<div>two</div>
<div>three</div>

<div>one</div><div>two</div><div>three</div>

But in case of semantically inline elements it may matter:

<span>one</span>
<span>two</span>
<span>three</span>

<span>one</span><span>two</span><span>three</span>

In the case of separate lines the textual representation would be one two three while in the second case it would be onetwothree, which might matter to search robots and web readers. This is just a side note to point out that white space or lack of it between html elements is not always irrelevant regardless of how we style it for display.

3 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.