I bought this mug recently for use at work. Being a professional web developer, I decided it would establish me as the office’s king of irony. The joke on it isn’t unique, of course. I’ve seen it everywhere from t-shirts to conference presentations.
Most of you reading this have probably encountered this image at least once. It’s a joke we can all relate to, right? You try and do something simple with CSS, and the arcane ways in which even basic properties interact inevitably borks it up.
If this joke epitomizes the collective frustration that developers have with CSS, then at the risk of ruining the fun, I thought it would be interesting to dissect the bug at its heart, as a case study in why people get frustrated with CSS.
See the Pen CSS is Awesome by Brandon (@brundolf) on CodePen.
There are three conditions that have to be met for this problem to occur:
- The content can’t shrink to fit the container
- The container can’t expand to fit the content
- The container doesn’t handle overflow gracefully
In real-world scenarios, the second condition is most likely the thing that needs to be fixed, but we’ll explore all three.
Fixing the content size
This is little bit unfair to the box’s content because the word AWESOME can’t fit on one line at the given font size and container width. By default, text wraps at white space and doesn’t break up words. But let’s assume for a moment that we absolutely cannot afford to change the container’s size. Perhaps, for instance, the text is a blown-up header on a site that’s being viewed on an especially small phone.
Breaking up words
To get a continuous word to wrap, we have to use the CSS property
word-break. Setting it to
break-all will instruct the browser to break up words if necessary to wrap text content within its container.
See the Pen CSS is Awesome: word-break by Brandon (@brundolf) on CodePen.
In this case, the only way to make the content more responsive was to enable word breaking. But there are other kinds of content that might be overflowing. If
word-wrap were set to
nowrap, the text wouldn’t even wrap in-between words. Or, the content could be a block-level element, whose
min-width is set to be greater than the container’s width.
Fixing the container size
There are many possible ways the container element might have been forced to not grow. For example:
flex. But the thing they all have in common, is that the width is being determined by something other than its content. This isn’t inherently bad, especially since there is no fixed height, which in most cases would cause the content to simply expand downwards. But if you run into a variation on this situation, it’s worth considering whether you really need to be controlling the width, or whether it can be left up to the page to determine.
Alternatives to setting
More often than not, if you set an element’s
width, and you set it in pixels, you really meant to set either
max-width. Ask yourself what you really care about. Was this element disappearing entirely when it lacked content because it shrunk to a width of 0? Set
min-width, so that it has dimension but still has room to grow. Was it getting so wide that a whole paragraph fit on one line and was hard to read? Set
max-width, so it won’t go beyond a certain limit, but also won’t extend beyond the edge of the screen on small devices. CSS is like an assistant: you want to guide it, not dictate its every move.
Overflow caused by flexbox
If one of your flex items has overflowing content, things get a little more complicated. The first thing you can do is check if you’re specifying its width, as in the previous section. If you aren’t, probably what’s happening is the element is “flex-shrinking”. Flex items first get sized following the normal rules;
width, content, etc. The resulting size is called their
flex-basis (which can also be set explicitly with a property of the same name). After establishing the flex basis for each item,
flex-shrink are applied (or
flex, which specifies both at once). The items grow and shrink in a weighted way, based on these two values and the container’s size.
flex-shrink: 0 will instruct the browser that this item should never get smaller than its flex basis. If the flex basis is determined by content (the default), this should solve your problem. be careful with this, though. You could end up running into the same problem again in the element’s parent. If this flex item refuses to shrink, even when the flex container is smaller than it, it’ll overflow and you’re back to square one.
Sometimes there’s just no way around it. Maybe the container width is limited by the screen size itself. Maybe the content is a table of data, with rows that can’t be wrapped and columns that can’t be collapsed any further. We can still handle the overflow more gracefully than just having it spill out wherever.
The most straightforward solution is to hide the content that’s overflowing. Setting
overflow: hidden; will simply cut things off where they reach the border of the container element. If the content is of a more aesthetic nature and doesn’t include critical info, this might be acceptable.
See the Pen CSS is Awesome: overflow:hidden by Brandon (@brundolf) on CodePen.
If the content is text, we can make this a little more visually appealing by adding
text-overflow: ellipsis;, which automatically adds a nice little “…” to text that gets cut off. It is worth noting, though, that you’ll see slightly less of the actual content to make room for the ellipsis. Also note that this requires
overflow: hidden; to be set.
See the Pen CSS is Awesome: ellipsis by Brandon (@brundolf) on CodePen.
The preferable remedy is usually going to be setting
overflow-x: auto;. This gives the browser the go-ahead to add a scroll bar if the content overflows, allowing the user to scroll the container in that direction.
See the Pen CSS is Awesome: overflow:auto by Brandon (@brundolf) on CodePen.
This is a particularly graceful fallback, because it means that no matter what, the user will be able to access all of the content. Plus, the scrollbar will only appear if it’s needed, which means it’s not a bad idea to add this property in key places, even if you don’t expect it to come into play.
Why does this conundrum resonate so universally with people who have used CSS?
CSS is hard because its properties interact, often in unexpected ways. Because when you set one of them, you’re never just setting that one thing. That one thing combines and bounces off of and contradicts with a dozen other things, including default things that you never actually set yourself.
One rule of thumb for mitigating this is, never be more explicit than you need to be. Web pages are responsive by default. Writing good CSS means leveraging that fact instead of overriding it. Use percentages or viewport units instead of a media query if possible. Use
min-width instead of
width where you can. Think in terms of rules, in terms of what you really mean to say, instead of just adding properties until things look right. Try to get a feel for how the browser resolves layout and sizing, and make your changes and additions on top of that judiciously. Work with CSS, instead of against it.
Another rule of thumb is to let either width or height be determined by content. In this case, that wasn’t enough, but in most cases, it will be. Give things an avenue for expansion. When you’re setting rules for how your elements get sized, especially if those elements will contain text content, think through the edge cases. “What if this content was pared down to a single character? What if this content expanded to be three paragraphs? It might not look great, but would my layout be totally broken?”
CSS is weird. It’s unlike any other code, and that makes a lot of programmers uncomfortable. But used wisely it can, in fact, be awesome.
Obligatory link to the famous (and very prescient) article “A Dao of Web Design” by John Alsop: https://alistapart.com/article/dao
An awesome quote from that which ties in well with your thoughts:
“If you use style sheets properly, to suggest the appearance of a page, not to control the appearance of a page, and you don’t rely on your style sheet to convey information, then your pages will “work” fine in any browser, past or future.”
Embrace the inherit flexibility – don’t fight against it. :-)
From a developer perspective, I agree 100%. Unfortunately, no matter how hard you argue for that, some (dare I say, most), clients – and even designers and project managers – have a very narrow view of “work fine in any browser”. Basically, if a page component doesn’t look exactly the same in every browser, then it doesn’t work and you’re an incompetent developer (I’m paraphrasing). Maybe I need to learn how to persuade better, but sometimes people just want to spend money for the sake of spending money, so I bill them for it.
I also did a pen aften I recieved that mug too :-) https://codepen.io/netsi1964/pen/QEVKzz
I too have made a pen:
See the Pen CSS is awesome by Andy Parsons (@andparsons) on CodePen.
Classic “fight with it, not against it”. My life became much easier as a dev once I delved deep into the HTML and CSS specs, studied the default styling and properties for each and every element, and then used it in my favour.
Ironically, seems like the break-word example is broken in Firefox :)
I always enjoyed the original image unironically, because it beautifully illustrates the power of CSS. After all, just try doing that same thing in a single element without CSS. The only things I can think of require either
embed, and are terrible hacks for what is just three words and a box. And they’d all break the ability to drag-select the text in a single block.
All solutions are min-funny: 25%; But what was the original design “supposed” to look like? No one knows ;)
I could be wrong – it happens from time to time – but isn’t this “issue” the browser’s fault? Why do we blame CSS for how the browser renders content by default?
I’m missing an important reference in this article: I’m pretty sure the illustration on the mug refers to Internet Explorer. Up to version 6 (the one that had that crazy 90ish percent market share because it came pre-installed with Windows XP) it drove web developers crazy by not allowing the simple setup the mug shows.
Whatever you would do to your CSS, IE 6 would just stretch the box containing the long word (“AWESOME”) to make it fit, even if a fixed width was set on it.
Fighting for browser compatibility (“This page is optimized for Netscape Version 5+ and a resolution of 1024×768 px.”) really was another beast back then.
That’s not how it was taken by the community when it appeared—in March 2009, according to several sources, so I doubt it referred to IE6 and Netscape 5—but I’ve pinged the creator to ask him if he’d drop by and explain the background.
Interesting. Although, I still stand by what I said about it not being CSS’ fault. So, if your comment about IE is true, shouldn’t the mug read “IE IS AWFUL”?
@Eric: Cool, I’m really curious.
Well, my work totally had to support IE 6 in 2009, but I’m over there in Germany and sadly, our browser landscape (regarding IE) is usually some years behind the states. So I was probably pretty biased on my evaluation of the mug’s origins.
@James: I had rather read it as “CSS IS AWESOME [if it’s treated correctly]”
Hi there! I’m Steve, the original creator of the CSS IS AWESOME design.
Eric asked if I could pop by and discuss the “background and original meaning” of CSS IS AWESOME. Well, I wish it was more interesting…
It was 2009 and I’d spent what seemed like hours trying to do something in CSS that I already knew I could do in seconds with tables. I was trying really hard to do it with CSS because that’s what you’re supposed to do, but I just wasn’t very good at it (spoiler alert: I’m still not very good at it).
I do have a slightly better grasp on the concept of overflow now, but at the time it just blew my mind that someone thought the default behavior should be to just have the text honk right out of the box, instead of just making the box bigger like my nice, sensible tables had always done.
Anyway, I just had this moment of pure frustration and, instead of solving the problem properly, I spent 5 minutes creating a snarky mug and went back to using tables. Because that’s my signature move in times of crisis.
That’s really all there was to it. It wasn’t directed at a specific browser or person or anything like that. I thought maybe a few people might relate to the experience and buy a dumb mug but, holy cow, the places it has gone.
PS: It’s my sincere hope that my dumb joke has not offended anybody involved with the evolution of CSS over the years. I honestly do appreciate the complexity of the subject and how annoying it can be to have someone drive by with a cheap joke premised on their own failure to understand something.
Aww. Really interesting stuff. I still liked my interpretation though. :D
Thanks for sharing this! I do like Florian’s interpretation, and I stand behind my hatred of browsers. They can’t agree on much, and it leaves developers to resort to things like autoprefixer, multiple file types for the same resource, SVG hacks, polyfills, and confusing mugs. :)
Wow, I definitely did not expect to get a comment from the original creator of the mug. I’m flattered :)
In fairness, I would bet that CSS wasn’t actually very awesome in 2009. I myself didn’t start using it until 2012, so I don’t know firsthand, but even in 2012 things like float hacks were still common practice.
Anyway, thanks so much for the added context, and thanks for the fantastic mug!
Missing one alternative option though: Hyphenation. Might solve the “breaking out of the box” issue a bit more elegantly than overflow manipulation.
Couldn’t agree more! This is what I like about CSS.
All the solutions except ellipsis failed on Firefox mobile. CSS is not awesome. Fight it some more.
If you have control over the Html you can make the first case a bit prettier with optional hyphenation marks ():
Since the case in question assumes that the content and container are not in their normal (ideal) state, whether because of screen size or some other factor, we wouldn’t want to add a hyphen in the markup itself. However, you’re right to point out CSS’s
hyphensproperty, which I was unaware of. The first (word-break) solution would absolutely benefit from
I think the Mug 2.0 is ready to ship !
Interestingly enough, I never saw this image as
“You try and do something simple with CSS, and the arcane ways in which even basic properties interact inevitably borks it up”
I always interpreted this image are more of a symbolic thing. Meaning CSS is so powerful it broke the mould and allowed developers to think out of the box with their designs.
But now I see exactly where you’re coming from and you’ve opened my eyes :)
Sorry if this is needlessly nitpicky, but in the paragraph under the heading Fixing the content size you state “But let’s assume for a moment that we absolutely cannot afford to change the container’s size.”
This sentence should replace the word “size” with “width” as you increased the container’s height with your solution.
Given the constraints, I assumed you’d adjust the font-size.
I (like many people) used this in a presentation on Debuging CSS once. It culminated in me fixing bugs until I ended up with a pure CSS Discoball:
Try doing that with tables ;P
I love that we have such a beloved universal symbol of frustration with CSS. We’ve all been there.
I have an answer with SVG, but you are not going to like it:
Good idea, but it does not work with Microsoft Edge !
I seriously had never seen this mug anywhere else, and now my heart is growing three sizes reading this post, thank you :)
My first mentor owned this mug, and gave it to me when she moved on from our company, and I’ve treasured it ever since (7 years and 3 jobs) — it was my office beer mug at my last job, and it’s my everyday seltzer mug at my current job.
And then, 2 months ago, I dropped it in our office kitchen, and it broke. I gave it to my brother b/c he’s a superglue wizard. If he can’t get it back to beverage-holder condition, I think I’ll use it as a mini planter so I can still have it on my desk. I know I could buy a new one, but that’s not really the point, of course :)
Anyway, thank you!! Cheers,
Oh the irony of your CSS (mug) breaking. Sorry to hear it, but it probably still works in Chrome.
hahaha @Kel, good point :)
CSS is awesome, why even use HTML ;P
From Christian Kaindl, after the buzzer: