Underline All Significant Words in the Directions Funny Pic
Styling the underlines that sit beneath links can be a tricky business, and I constantly forget what's the best approach depending on the situation. Thankfully however, John Jameson gets us up to speed in this guest post.
There are a bunch of different ways to style underlines. Maybe you remember the article Crafting link underlines on Medium. Medium wasn't trying to do anything crazy; they just wanted to create a pretty normal-looking line below their text.
It's a pretty basic underline, but it's a good size and it skips descenders too. Definitely nicer than most browsers' default. Well, it turns out Medium had to go through a lot of trouble to get that style on the web. Two years later, it's still just as hard to style a good-looking underline.
Goals
What's wrong with just using text-decoration: underline
? If we're talking about the ideal scenario, an underline should be able to do the following:
- Position itself below the baseline
- Skip descenders
- Change color, thickness, and style
- Repeat across wrapped text
- Work on any background
I think these are all pretty reasonable things to ask for, but as far as I know, there's no intuitive way to achieve all of them in CSS.
Approaches
So what are all the different ways we can underline text on the web?
Here are the ones I can think of:
-
text-decoration
-
border-bottom
-
box-shadow
-
background-image
- SVG filters
- Underline.js (canvas)
-
text-decoration-*
Let's go down the list one by one and talk about the good and bad parts of each approach.
text-decoration
text-decoration
is the most straightforward way to underline text. You apply a single property and that's all there is to it. At smaller sizes, it can look pretty decent, but increase the font size and the same line starts to feel clumsy.
See the demo.
The biggest problem with text-decoration
is its lack of customizability. It uses the color and font size of whatever text its applied to and there's no cross-browser way to change the style. More on that later.
Good
- Easy to use
- Positioned below the baseline
- Skips descenders by default in Safari and iOS
- Wraps across lines
- Works on any background
Bad
- Can't skip descenders in other browsers
- Can't change color, thickness, or style
border-bottom
border-bottom
offers a good balance between being quick and customizable. This approach uses a tried-and-true CSS border, which means you can change color, thickness, and style with ease.
This is what border-bottom
looks like on inline
elements:
See the demo.
The big gotcha is how far away the underline is from the text — it's completely below the descenders. You can address that by making elements inline-block
and reducing line-height
, but then you lose the ability to wrap text. Good for single lines, but not much else.
See the demo.
Additionally, you can use text-shadow
to cover up parts of the line near descenders, but you have to fake it by using the same color as whatever background it's on. That means it works only for solid-color backgrounds and not gradients or images.
See the demo.
At this point, there are four properties styling a single underline. That's a lot more work than text-decoration
.
Good
- Can skip descenders using
text-shadow
- Can change color, thickness, and style
- Can transition and animate color and thickness
- Wraps by default unless it's an
inline-block
- Works on any background unless using
text-shadow
Bad
- Positioned far away and difficult to reposition
- A lot of unrelated properties to get it just right
- Janky text selection when using
text-shadow
box-shadow
box-shadow
draws an underline with two inset box shadows: one to create a rectangle and a second to cover it up. That means you'll need a solid background for this to work.
See the Pen Underlines 5: box-shadow by John D. Jameson (@johndjameson) on CodePen.
You can use the same text-shadow
trick to fake gaps between the underline and the text's descenders. But if the line is a different color from the text — or even just thin enough — it doesn't really clash like text-decoration
does.
Good
- Can be positioned below the baseline
- Can skip descenders using
text-shadow
- Can change color and thickness
- Wraps across lines
Bad
- Can't change style
- Doesn't work on any background
background-image
background-image
comes the closest to everything we want and with the fewest gotchas. The idea is that you use linear-gradient
and background-position
to create an image that repeats itself horizontally across lines of text.
You'll have to display: inline;
this approach too.
See the demo.
This approach doesn't have to use linear-gradient
either. You can bring your own background image for some cool effects.
See the demo.
Good
- Can be positioned below the baseline
- Can skip descenders using
text-shadow
- Can change color, thickness (allows half pixels), and style
- Works with custom images
- Wraps across lines
- Works on any background unless using
text-shadow
Bad
- The image can resize differently across resolutions, browsers, and zoom levels
SVG filters
Here's an approach I've been toying around with: SVG filters. You can create an inline SVG filter
element that draws a line and then expands the text to mask out parts of the line we want to be transparent. Then you can give the filter
an an id
and reference it in CSS with something like filter: url('#svg-underline')
.
The advantage here is that the filter adds transparency without relying on text-shadow
. That means you can skip descenders on top of any background, including gradients and background images! This one works only on a single line of text though, so heads-up on that.
See the demo.
Here's what it looks like in Chrome and Firefox:
Browser support in IE, Edge, and Safari is problematic. It's hard to test for SVG filter support in CSS. You can use @supports
with filter
, but that only tests if the reference works — not the applied filter itself. My approach ends up doing some pretty gross browser sniffing, so double heads-up on that too.
Pros
- Positioned below the baseline
- Skips descenders
- Able to change color, thickness, and style
- Works on any background
Cons
- Doesn't wrap across lines
- Doesn't work in IE, Edge, or Safari, but you can fall back to
text-decoration
. Safari's underlines look good anyway.
Underline.js (Canvas)
Underline.js is fascinating. I think it's super impressive what Wenting Zhang was able to do with JavaScript and some attention to detail. If you haven't seen the Underline.js tech demo before, definitely stop reading for a minute and check it out. There's a fascinating nine-minute-long talk on how it works, but I'll give you the short version: it draws underlines with <canvas>
elements. It's a novel approach that works surprisingly well.
Despite the catchy name, Underline.js is a tech demo only. That means you won't be able to drop it into any projects without modifying it a whole bunch first.
It's worth bringing it up here as a proof of concept. <canvas>
has the potential to create beautiful, interactive underlines, but you'll have to write some custom JavaScript to get them working.
text-decoration-* properties
Remember the "more on that later" part? Well, here we are.
text-decoration
works fine by itself, but you can add a few experimental properties to customize the way it looks:
-
text-decoration-color
-
text-decoration-skip
-
text-decoration-style
Just don't get too excited. You know, browser support.
text-decoration-color
text-decoration-color
lets you change an underline's color separately from its text color. The property even has better-than-expected browser support — it works in Firefox and prefixed in Safari. Here's the catch: If you're not clearing descenders, Safari puts the line on top of the text. 🙃
Firefox:
Safari:
text-decoration-skip
text-decoration-skip
toggles skipping descenders in underlined text.
This property is non-standard and works only in Safari right now, so you need the -webkit-
prefix to use it. Safari enables this property by default though, which is why underlines skip descenders even on websites that don't specify it.
If you're using Normalize, know that recent versions disable the property to keep things consistent between browsers. You need to flip it back on if you want those dreamy underlines.
text-decoration-style
text-decoration-style
offers the same sorts of lines you'd expect from border-style
, but adds in wavy
lines too.
Here are the different values you can use:
-
dashed
-
dotted
-
double
-
solid
-
wavy
Right now, text-decoration-style
works only in Firefox, so here's a screenshot:
Look familiar?
What's missing?
The text-decoration-*
properties are far more intuitive than using other CSS properties to style underlines. But if we take another look at our earlier requirements, these properties don't offer a way to specify line thickness or position.
After doing a little research, I came across these two properties:
-
text-underline-width
-
text-underline-position
It looks like they were pitched in earlier drafts of CSS, but never implemented due to lack of interest. Hey, don't blame me.
Takeaways
So what's the best way to underline text?
It depends.
For small text, I recommend using text-decoration
and then optimistically applying text-decoration-skip
on top. It looks a little bland in most browsers, but underlines have looked that way forever and people don't seem to mind. Plus there's always the chance that if you're patient enough, all your underlines will look awesome later on without you having to change a thing.
For body text, probably use the background-image
approach. It works, it looks great, and there are Sass mixins for it. You can probably omit text-shadow
it if the underline is thin or in a different color from the text.
For single lines of text, use border-bottom
and whatever other properties you want to go with it.
And for skipping descenders on top of a gradient or background image, try using SVG filters. Or just avoid using an underline altogether.
In the future when browser support is better, the answer is text-decoration-*
all the way.
Also see Benjamin Woodruff's post CSS Underlines Suck, which coincidentally treads this ground in a similar way.
Source: https://css-tricks.com/styling-underlines-web/
0 Response to "Underline All Significant Words in the Directions Funny Pic"
Post a Comment