Tuesday, May 24, 2016

Injecting a Line Break

I had a little situation where I head a header with a span in it, and I wanted to make sure to put a line break before the span. For the record, there really isn't anything wrong with just chucking a
tag before it (and in fact the ability to show/hide that is very useful). But... it always feels a little weird to have to use HTML to achieve a layout thing.


So let's take a journey. A journey in which we say "But..." a lot.





Break right after this




and before this



A block level element would do it


Rather than a , we could use a

, and we'll get that break just by virtue of the div being a block-level element.


But we're using a span on purpose, because of the design. The text after the break should be inline/inline-block, because it's going to have a background and padding and such.



You can insert line breaks via pseudo element


It's easy:


h1 span::before {
content: "\A";
}

But... the is an inline element. The line break won't do anything! Just like a real line break won't do anything.


We can force that line break to work by making white space meaningful...


h1.two span::before {
content: "\A";
white-space: pre;
}

That actually works. But... because of the padding and background, it leaves a little chunk of that behind when the line breaks:



We could fix the awkward-left-edge-hugging on by using box-decoration-break: clone;, but... that just leaves a bigger chunk up top:




box-decoration-break is great for some issues, but not this one.


If we made the span inline-block, the break would happen within that block, which isn't what we want either:



Making the pseudo element block-level and leaving the span alone doesn't do the trick either:



You could get a little weird and inject the actual text with a pseudo element


This was Aaron Bushnell's idea. The trick here is to make the span block level, but then inject the text with a pseudo element and style it as an inline element.


h1 span {
display: block;
}
h1 span::before {
content: attr(data-text);
background: black;
padding: 1px 8px;
}



It works! But...


I've long been a fan of pseudo element trickery, but this feels slightly dangerous in that you may be hurting accessibility. I think some screen readers read pseudo elements, but I don't think all, nor are they supposed to. Not to mention you can't copy and paste all the text this way. At least the text is still maintained entirely in the HTML!


Exploiting table layout


My favorite idea came from Thierry Koblentz. Just make the span display: table; and you're done. It's not tabular data of course, but that doesn't matter. The face you can force table layout from CSS is all about exploiting the unique layout properties of table layout - not semantics.


h1 span {
display: table;
}


Live Demos


Including one where we just use a
, which is fine.


See the Pen Attempting a line break before and inline-block within a header by Chris Coyier (@chriscoyier) on CodePen.




Injecting a Line Break is a post from CSS-Tricks

No comments:

Post a Comment