2

Inline-block elements default to the height of their container's line height - when they have content. I'm finding that empty and whitespace-only inline block elements default to height:0 (this is on Firefox).

Is there a way I can make inline block elements that are empty gain the height of their container's line height the same as inline block elements that contain text?

Hardcoding the height isn't an option, nor is adding random HTML like   to make the elements not "empty". I've looked for duplicates and was surprised not to find any.

So for example, in this demo I'd like the first span (around a regular space) to appear how the second span (around a  ) appears:

.inlineblock {
  display: inline-block;
  border: 2px solid #FF0000;
}
Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"> </span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

...rather than how it currently appears, which is like this, with the first span height:0:

enter image description here


I've tried: giving it a fixed width, height: auto;, height: inherit;, vertical align, and giving it a position:relative paragraph and/or inline-block container then height: 100%;, but no success.

.inlineblock {
  display: inline-block;
  border: 2px solid #FF0000;
}
.width {
  width: 5px;
} 
.percent {
  height: 100%;
}
.relative {
  position: relative;
}
.vert {
  vertical-align: top;
}
.auto {
  height: auto;
}
.inherit {
  height: inherit;
}
<p class="relative">Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"> </span>adipiscing elit, sed do<span class="inlineblock percent"> </span>eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation<span class="relative"><span class="inlineblock percent"> </span></span>ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in<span class="inlineblock vert"> </span>voluptate velit esse<span class="inlineblock inherit"> </span>cillum dolore<span class="inlineblock auto"> </span>eu fugiat<span class="inlineblock width"> </span>nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
user56reinstatemonica8
  • 32,576
  • 21
  • 101
  • 125
  • 1
    Just to be sure I understand, by "hardcoding is not an option" you mean you can't add a height of 1em to the span (which makes it the same as whatever the default character height is)? – salad_bar_breath Aug 11 '15 at 15:20
  • Cause it does work: http://jsfiddle.net/Doug021786/vjbaeu21/ – salad_bar_breath Aug 11 '15 at 15:21
  • @Douglas But it doesn't work well when the font size is set explicitly: http://jsfiddle.net/wggpvb2g/1/. – cdMinix Aug 11 '15 at 15:26
  • Ahh okay, good point @cdMinix – salad_bar_breath Aug 11 '15 at 15:29
  • @Douglas Yeah I'm trying to avoid that if possible, since it creates possible CSS conflicts, but I might need to resort to something like that. Also it should be 1.2em I believe to cover the descender area below the baseline; this also behaves differently regarding vertical align (but that can be fixed with manual vertical align) - http://jsfiddle.net/vjbaeu21/2/ – user56reinstatemonica8 Aug 11 '15 at 15:31
  • 1
    @Douglas is right. It does work well even with differing `font-size` of the parent as long as the height is set to 1em. The reason for this problem is that the empty `inline-block`s are treated just like inlines. There is no `padding` and no character to set the `font-size` and `line-height` for that. Hence they just collapse in absence of `width` and `height`. Give it a `height` (1em), give it some `padding`, and give it a `vertical-align` as well. See here: http://jsfiddle.net/abhitalks/wggpvb2g/2/ – Abhitalks Aug 11 '15 at 15:34
  • @cdMinix the issue in your fiddle is actually a quirk to do with vertical aligning - setting `vertical-align: top;` actually fixes it. http://jsfiddle.net/wggpvb2g/3/ I thought explicit font sizes would be a big problem, but it looks like it's actually not too bad. – user56reinstatemonica8 Aug 11 '15 at 15:48

3 Answers3

2

As commented and demonstrated by @Douglas, if you want to avoid content then use a height of 1em. em will be relative to the parent and as such will scale well with the parent's font-size.

As per the ref here: http://www.w3.org/TR/css3-values/#font-relative-lengths

...the font-relative lengths refer to the font metrics of the element on which they are used. The exception is when they occur in the value of the ‘font-size’ property itself, in which case they refer to the computed font metrics of the parent element..

In your case, the spans have no explicitly defined font-size hence they inherit it from the parent. Height of 1em will now be relative to its own inherited font-size.

The reason for your problem is that the empty inline-blocks are treated just like inlines. There is no padding and no content to set the font-size and line-height for that. Hence they just collapse in absence of width and height. Give it a height (1em), give it some padding (if required), and give it a vertical-align as well.

Example Fiddle: jsfiddle.net/abhitalks/wggpvb2g/2

Example Snippet:

p:first-of-type { font-size: 11px; }
.inlineblock {
  display: inline-block;
  border: 2px solid #f00;
  vertical-align: middle;
  padding: 2px; height: 1em;
}
<p>Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"></span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
<p>Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"></span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
  • Valuable explanation, thanks. I've tried to find an example case where relying on `height: 1em;` suffers from conflicts but it does actually seem pretty robust. One slight suggested ammendment: `vertical-align: top;` appears to be closer to the default behaviour of inline blocks with content than `vertical-align: middle;` - [related question on vertical align quirks between inline blocks with and without content](http://stackoverflow.com/questions/24862861/empty-div-vs-div-with-text-having-inline-block-property) – user56reinstatemonica8 Aug 11 '15 at 15:52
  • @user568458: `middle` will have no problems and will neatly align. You can use `bottom` as well. Just go with whatever suits you best. – Abhitalks Aug 11 '15 at 15:54
  • 1
    This assumes `line-height: 1`. The initial `line-height` is implementation-dependent, but the spec recommends a value between 1 and 1.2 – Oriol Aug 11 '15 at 15:55
  • @Oriol: Hmmmm.. yes, agreed. Am on mobile now, can't check. But, this should work fine within those limits for Op's use case unless it is set too high or low. – Abhitalks Aug 11 '15 at 16:09
1

The following makes it possible, and doesn't depend on line-height, font-size or any other css properties being set, but it is a rather hacky solution.

.inlineblock {
  display: inline-block;
}    
.inlineblock::after {
  display: inline-block;
  content: "\007C\00a0\00a0";
  border: 2px solid #FF0000;
}
Lorem ipsum dolor sit amet, consecteturadipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock"> </span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Note that \007C\00a0\00a0 stands for nbsp; in a way css can understand it.

This solution creates a new pseudo element instead of modifying the original elements height, but this may be the closest you can get without altering the html.

cdMinix
  • 655
  • 1
  • 7
  • 29
1

You can add an inline-block pseudo-element:

.inlineblock::after {
  content: '';
  display: inline-block;
}

.inlineblock {
  display: inline-block;
  border: 2px solid #FF0000;
}
.inlineblock:after {
  content: '';
  display: inline-block;
}
Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"> </span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Alternatively, you can insert a normal space and use white-space to prevent it from collapsing:

.inlineblock::after {
  content: ' ';
  white-space: pre-wrap; /* or pre */
}

.inlineblock {
  display: inline-block;
  border: 2px solid #FF0000;
}
.inlineblock:after {
  content: ' ';
  white-space: pre-wrap;
}
Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"> </span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Or insert an zero-width space

.inlineblock::after {
  content: '​'; /* or \00200B */
}

.inlineblock {
  display: inline-block;
  border: 2px solid #FF0000;
}
.inlineblock:after {
  content: '​';
}
Lorem ipsum dolor sit amet, consectetur<span class="inlineblock"> </span>adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur<span class="inlineblock">&nbsp;</span>sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
Oriol
  • 274,082
  • 63
  • 437
  • 513