You don’t need a media query for that: #1 Inline content separators
A few months ago I picked up a task to fix a bug in one of our components which contained pipe separators to distinguish between different pieces of content.
One of the things I noticed when I was looking through the CSS was that the use of media queries meant the component was very inflexible. That might sound counter intuitive, but the media queries meant that the content had to wrap and respond in a very particular way — this was the cause of the bug — the content was wrapping at an awkward point and it didn’t work in a new scenario.
My goal became:
Create a more flexible component which allows the text to wrap based on the content rather than the viewport size.
Check out the codepen if you just wanna get to the code. It’s cool I know how it is. 👍
Essentially I had situation like the images below — two words with a separator of some kind in between, when the text wraps hide the separator.
Typically we might approach this by adding in a breakpoint to determine when the text will wrap, and at the same time hide the separator in some way, like using display:none, or similar.
The problem with this, is that you are wrapping based on a particular viewport size and as a result it’s matched to a particular size of content. Ideally this content would wrap only when it needs to, regardless of the viewport or container.
To solve my bug and achieve the outcome I wanted, I needed to meet a few criteria:
- No media queries
- When the text needed to wrap the whole block would wrap on a new line (this made the content easier to read)
- Once it wrapped there would be no separator hanging off the end
The below Codepen is the approach i came up with, you can stop here and have a play yourself, or carry on and read through what each part does.
First, the paragraph, most of the CSS in the paragraph is not overly important, it’s used to center and style. However the flexbox and overflow properties are important.
(Note: you can also use
overflow-x:auto here, I used hidden in this example to make it more explicit for the sake of the article).
We use flexbox to wrap the items when they no longer fit within the container or viewport, this is how we will ensure the content wraps in blocks.
The overflow property is what allows the pipes to disappear when the content wraps — because we aren’t really removing them, so much as clipping them (we’ll get back to this).
Each piece of content inside the paragraph is wrapped in a
span this could be a single word or multiple, it doesn’t actually matter. The spans simply allow us to target each item and apply some styling.
The first item, is very simple, it inherits all the styling from the paragraph and then adds a right padding value of 10px (
padding-right:10px;) — we’ll come back to this.
The second item is where most of the hard work is done. I have created the separator using a 1px pseudo-element but this can really be done however you want. The important code comes next:
First we need to add some padding, in this case, it’s on the left, and only 5px, and then finally we add a transform property with a value of
translateX(-5px) . This number needs to be half the value of the
padding-right value we added to the first item. It’s what makes the whole code work.
On the first item we added a 10px padding which set the space we wanted between the two items, on the second item we add a left padding of half that value and then undo that padding with a transform. When the text wraps this offset pulls the pipe outside of the paragraph region hiding it from view because of the overflow property we added on the paragraph.
If I disable the overflow, you can see in the image below where the separator ends up sitting. By setting overflow on the paragraph this hide the separator but only when the text wraps onto a new line and ensures that the text aligns on the left.
So finally, we are left with the below result:
The benefit of this approach is that because it’s dependant on the content, it will react to the width of the parent container, not just the viewport, so if you use the component in multiple places and in some places the parent has a smaller width the component will adjust accordingly. The same applies if you change the length of the content.
It’s easy to reach for media queries, but they aren’t always the best solution, don’t just think about viewports, think about the content and how to best represent that content regardless of viewport width.
Hopefully this approach will solve a problem, or inspire a whole other solution for your projects.