Subscribers: Update Your Feed URLs

To our feed subscribers. In case you haven’t heard. Feedburner is dead man walking. As a result, we changed our RSS and Atom feed URLs to host them directly at DigWP.com. So if you want to continue getting our awesome WP-related content delivered to your feed reader, take a moment to update your feed URLs. Our new (and permanent) feed URLs:

Visit the DigWP Archives for more feed options.

Direct link to article | View post at DigWP.com

Migrating Book Accounts

Heads up! We’re migrating all book accounts to the new bookstore at Perishable Press Books. This will make it easier to manage everything under one roof. To transfer your account to the new site, send a quick email and let us know 1) the site/URL where you purchased the book (e.g., DigWP.com), and 2) your registered username or email address. Thank you!

Direct link to article | View post at DigWP.com

How to Safely Share Your Email Address on a Website

Spammers are a huge deal nowadays. If you want to share your contact information without getting overwhelmed by spam email you need a solution. I run into this problem a few months ago. While I was researching how to solve it, I found different interesting solutions. Only one of them was perfect for my needs.

In this article, I am going to show you how to easily protect your email address from spam bots with multiple solutions. It’s up to you to decide what technique fits your needs.

The traditional case

Let’s say that you have a website. You want to share your contact details, and you don’t want to share only your social links. The email address must be there. Easy, right? You type something like this:

<a href="mailto:email@address.com">Send me an Email</a>

And then you style it according to your tastes.

Well, even if this solution works, it has a problem. It makes your email address available to literally everyone, including website crawlers and all sorts of spam bots. This means that your inbox can be flooded with tons of unwanted rubbish like promotional offers or even some phishing campaign.

We are looking for a compromise. We want to make it hard for bots to get our email addresses, but as simple as possible for normal users.

The solution is obfuscation.

Obfuscation is the practice of making something difficult to understand. This strategy is used with source code for multiple reasons. One of them is hiding the purpose of the source code to make tampering or reverse-engineering more difficult. We will first look at different solutions that are all based on the idea of obfuscation.

The HTML approach

We can think of bots as software that browse the web and crawl through web pages. Once a bot obtains an HTML document, it interprets the content in it and extracts information. This extraction process is called web scraping. If a bot is looking for a pattern that matches the email format, we can try to disguise it by using a different format. For example, we could use HTML comments:

<p>If you want to get in touch, please drop me an email at<!-- fhetydagzzzgjds --> email@<!-- sdfjsdhfkjypcs -->addr<!-- asjoxp -->ess.com</p>

It looks messy, but the user will see the email address like this:

If you want to get in touch, please drop me an email at email@address.com

Pros:

  • Easy to set up.
  • It works with JavaScript disabled.
  • It can be read by assistive technology.

Cons:

  • Spam bots can skip known sequences like comments.
  • It doesn’t work with a mailto: link.

The HTML & CSS approach

What if we use the styling power of CSS to remove some content placed only to fool spam bots? Let’s say that we have the same content as before, but this time we place a span element inside:

<p>If you want to get in touch, please drop me an email at <span class="blockspam" aria-hidden="true">PLEASE GO AWAY!</span> email@<!-- sdfjsdhfkjypcs -->address.com</p>.

Then, we use the following CSS style rule:

span.blockspam {
  display: none;
}

The final user will only see this:

If you want to get in touch, please drop me an email at email@address.com.

…which is the content we truly care about.

Pros:

  • It works with JavaScript disabled.
  • It’s more difficult for bots to get the email address.
  • It can be read by assistive technology.

Con:

  • It doesn’t work with a mailto: link.

The JavaScript approach

In this example, we use JavaScript to make our email address unreadable. Then, when the page is loaded, JavaScript makes the email address readable again. This way, our users can get the email address.

The easiest solution uses the Base64 encoding algorithm to decode the email address. First, we need to encode the email address in Base64. We can use some websites like Base64Encode.org to do this. Type in your email address like this:

A large textarea to paste an email address with a series of options beneath it for how to encode the text.

Then, click the button to encode. With these few lines of JavaScript we decode the email address and set the href attribute in the HTML link:

var encEmail = "ZW1haWxAYWRkcmVzcy5jb20=";
const form = document.getElementById("contact");
form.setAttribute("href", "mailto:".concat(atob(encEmail)));

Then we have to make sure the email link includes id="contact" in the markup, like this:

<a id="contact" href="">Send me an Email</a>

We are using the atob method to decode a string of Base64-encoded data. An alternative is to use some basic encryption algorithm like the Caesar cipher, which is fairly straightforward to implement in JavaScript.

Pros:

  • It’s more complicated for bots to get the email address, especially if you use an encryption algorithm.
  • It works with a mailto: link.
  • It can be read by assistive technology.

Con:

  • JavaScript must be enabled on the browser, otherwise, the link will be empty.

The embedded form approach

Contact forms are everywhere. You certainly have used one of them at least once. If you want a way for people to directly contact you, one of the possible solutions is implementing a contact form service on your website.

Formspree is one example of service which provides you all the benefits of a contact form without worrying about server-side code. Wufoo is too. In fact, here is a bunch you can consider for handling contact form submissions for you.

The first step to using any form service is to sign up and create an account. Pricing varies, of course, as do the features offered between services. But one thing most of them do is provide you with an HTML snippet to embed a form you create into any website or app. Here’s an example I pulled straight from a form I created in my Formspring account

<form action="https://formspree.io/f/[my-key]" method="POST">
  <label> Your email:
    <input type="email" name="email" />
  </label>
  <label> Your message:
    <textarea name="message"></textarea>
  </label>
  <!-- honeypot spam filtering -->
  <input type="text" name="_gotcha" style="display:none" />
  <button type="submit">Send</button>
</form>

In the first line, you should customize action based on your endpoint. This form quite basic, but you can add as many fields as you wish.

Notice the hidden input tag on line 9. This input tag helps you filter the submissions made by regular users and bots. In fact, if Formspree’s back-end sees a submission with that input filled, it will discard it. A regular user wouldn’t do that, so it must be a bot.

Pros:

  • Your email address is safe since it is not public.
  • It works with Javascript disabled.

Con:

  • Relies on a third-party service (which may be a pro, depending on your needs)

There is one other disadvantage to this solution but I left it out of the list since it’s quite subjective and it depends on your use case. With this solution, you are not sharing your email address. You are giving people a way to contact you. What if people want to email you? What if people are looking for your email address, and they don’t want a contact form? A contact form may be a heavy-handed solution in that sort of situation.

Conclusion

We reached the end! In this tutorial, we talked about different solutions to the problem of online email sharing. We walked through different ideas, involving HTML code, JavaScript and even some online services like Formspree to build contact forms. At the end of this tutorial, you should be aware of all the pros and cons of the strategies shown. Now, it’s up to you to pick up the most suitable one for the your specific use case.


How to Safely Share Your Email Address on a Website originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

6 Creative Ideas for CSS Link Hover Effects

Creating CSS link hover effects can add a bit of flair to an otherwise bland webpage. If you’ve ever found yourself stumped trying to make a slick hover effect, then I have six CSS effects for you to take and use for your next project.

A default link hover effect above a styled link hover effect with a rainbow underline.

Let’s get right to it!

I know we’re talking about :hover and all, but it can sometimes (but maybe not always) be a good idea lump :focus in as well, as not all interactions are directly from a mouse, but perhaps a tap or keystroke.

This effect applies a box shadow to the inline link, altering the color of the link text in the process. We start with padding all around the link, then add a negative margin of the same value to prevent the padding from disrupting the text flow.

We will use box-shadow instead of the background property since it allows us to transition.

a {
  box-shadow: inset 0 0 0 0 #54b3d6;
  color: #54b3d6;
  margin: 0 -.25rem;
  padding: 0 .25rem;
  transition: color .3s ease-in-out, box-shadow .3s ease-in-out;
}
a:hover {
  box-shadow: inset 100px 0 0 0 #54b3d6;
  color: white;
}

Here’s a fun one where we swap the text of the link with some other text on hover. Hover over the text and the linked text slides out as new text slides in.

Easier to show than tell.

There’s quite a bit of trickery happening in this link hover effect. But the magic sauce is using a data-attribute to define the text that slides in and call it with the content property of the link’s ::after pseudo-element.

First off, the HTML markup:

<p>Hover <a href="#" data-replace="get a link"><span>get a link</span></a></p>

That’s a lot of inline markup, but you’re looking at a paragraph tag that contains a link and a span.

Let’s give link some base styles. We need to give it relative positioning to hold the pseudo-elements — which will be absolutely positioned — in place, make sure it’s displayed as inline-block to get box element styling affordances, and hide any overflow the pseudo-elements might cause.

a {
  overflow: hidden;
  position: relative;
  display: inline-block;
}

The ::before and ::after pseudo-elements should have some absolute positioning so they stack with the actual link. We’ll make sure they are set to the link’s full width with a zero offset in the left position, setting them up for some sliding action.

a::before,
a::after {
 content: '';
  position: absolute;
  width: 100%;
  left: 0;
}

The ::after pseudo-element gets the content from the link’s data-attribute that’s in the HTML markup:

a::after {
  content: attr(data-replace);
}

Now we can transform: translate3d() the ::after pseudo-element element to the right by 200%. We move it back into position on :hover. While we’re at it, we can give this a zero offset n the top direction. This’ll be important later when we use the ::before pseudo-element like an underline below the text.

a::after {
  content: attr(data-replace);
  top: 0;
  transform-origin: 100% 50%;
  transform: translate3d(200%, 0, 0);
}

a:hover::after,
a:focus::after {
  transform: translate3d(0, 0, 0);
}

We’re also going to transform: scale() the ::before pseudo-element so it’s hidden by default, then scale it back up on :hover. We’ll make it small, like 2px in height, and pin it to the bottom so it looks like an underline on the text that swaps in with ::after.

a::before {
  background-color: #54b3d6;
  height: 2px;
  bottom: 0;
  transform-origin: 100% 50%;
  transform: scaleX(0);
}

a:hover::before,
a:focus::before {
  transform-origin: 0% 50%;
  transform: scaleX(1);
}

The rest is all preference! We drop in a transition on the transform effects, some colors, and whatnot to get the full effect. Those values are totally up to you.

View full CSS
a {
  overflow: hidden;
  position: relative;
  display: inline-block;
}

a::before,
a::after {
 content: '';
  position: absolute;
  width: 100%;
  left: 0;
}
a::before {
  background-color: #54b3d6;
  height: 2px;
  bottom: 0;
  transform-origin: 100% 50%;
  transform: scaleX(0);
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
}
a::after {
  content: attr(data-replace);
  height: 100%;
  top: 0;
  transform-origin: 100% 50%;
  transform: translate3d(200%, 0, 0);
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
  color: #54b3d6;
}

a:hover::before {
  transform-origin: 0% 50%;
  transform: scaleX(1);
}
a:hover::after {
  transform: translate3d(0, 0, 0);
}

a span {
  display: inline-block;
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
}

a:hover span {
  transform: translate3d(-200%, 0, 0);
}

This is a pretty popular effect I’ve seen used in quite a few places. The idea is that you use the link’s ::before pseudo-element as a thick underline that sits slightly behind the actual text of the link. Then, on hover, the pseudo-element expands to cover the whole thing.

OK, some base styles for the link. We want no text-decoration since ::before will act like one, then some relative positioning to hold ::before in place when we give that absolute positioning.

a {
  text-decoration: none;
  position: relative;
}

Now let’s set up ::before by making it something like 8px tall so it looks like a thick underline. We’ll also give it absolute positioning so we have control to make it the full width of the actual link while offsetting it so it’s at the left and is just a smidge off the bottom so it looks like it’s subtly highlighting the link. May as well give it z-index: -1 so we’re assured it sits behind the link.

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
}

Nice, nice. Let’s make it appear as though ::before is growing when the link is hovered. All we need is to change the height from 3px to 100%. Notice that I’m also dropping the bottom offset back to zero so the background covers more space when it grows.

a:hover::before {
  bottom: 0;
  height: 100%;
}

Now for slight transition on those changes:

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
  transition: all .3s ease-in-out;
}
View full CSS
a {
  text-decoration: none;
  color: #18272F;
  font-weight: 700;
  position: relative;
}

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
  transition: all .3s ease-in-out;
}

a:hover::before {
  bottom: 0;
  height: 100%;
}

I personally like using this effect for links in a navigation. The link starts in one color without an underline. Then, on hover, a new color slides in from the right while an underline slides in from the left.

Neat, right? There’s a lot of motion happening in there, so you might consider the accessibility implications and wrap it all in a prefers-reduced-motion query to replace it with something more subtle for those with motion sensitivities.

Here’s how it works. We give the link a linear background gradient with a hard stop between two colors at the halfway mark.

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
}

We make the background double the link’s width, or 200%, and position it all the way over to the left. That way, it’s like only one of the gradients two colors is showing.

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
}

The magic happens when we reach for a couple of non-standard -webkit-prefixed properties. One strips the color out of the text to make it transparent. The other clips the background gradient to the text so it appears the text is actually the color of the background.

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

Still with me? Now let’s make the link’s faux underline by putting ::before to use. We’ll give it the same color we gave the on the hidden portion of the link’s background gradient and position it under the actual link so it looks like a proper text-decoration: underline.

a:before {
  content: '';
  background: #54b3d6;
  display: block;
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 0;
  height: 3px;
}

On hover, we slide ::before into place, coming in from the left:

a:hover {
 background-position: 0;
}

Now, this is a little tricky. On hover, we make the link’s ::before pseudo-element 100% of the link’s width. If we were to apply this directly to the link’s hover, we’d make the link itself full-width, which moves it around the screen. Yikes!

a:hover::before {
  width: 100%;
}

Add a little transition to smooth things out:

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: all 0.3s ease-in-out;
}
View full CSS
a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  display: inline-block;
  padding: 5px 0;
  position: relative;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: all 0.3s ease-in-out;
}

a:before {
  content: '';
  background: #54b3d6;
  display: block;
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 0;
  height: 3px;
  transition: all 0.3s ease-in-out;
}

a:hover {
 background-position: 0;
}

a:hover::before {
  width:100%;
}

We can’t do text-decoration-color: rainbow, but we can fake it with a little background magic mixed with linear gradients.

First, we remove the link’s text-decoration:

a {
  text-decoration: none;
}

Now for those gradients. We chain two linear gradients together on the same background property. One gradient is the initial color before hover. The second is the rainbow on hover.

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
}

Let’s make the background size a mere 3px tall so it looks like, you know, an underline. We can size both gradients together on the background-size property so that the initial gradient is full width and 3px tall, and the rainbow is zero width.

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
}

Now we can position the background gradients — at the same time on the background-position property — so that the first gradient is fully in view and the rainbow is pushed out of view. Oh, and let’s make sure the background isn’t repeating while we’re at it.

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
  background-position: 100% 100%, 0 100%;
  background-repeat: no-repeat;
}

Let’s update the background-size on hover so that the gradients swap values:

a:hover {
  background-size: 0 3px, 100% 3px;
}

And, finally, a little transition when the hover takes place:

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
  background-position: 100% 100%, 0 100%;
  background-repeat: no-repeat;
  transition: background-size 400ms;
}

Voilà!

Geoff Graham actually covered this same one recently when he dissected Adam Argyle’s slick hover effect. In his demo, a background color enters from the left behind the link, then exits to the right on mouse out.

My version pares down the background so it’s more of an underline.

a {
  position: relative;
}

a::before {
    content: '';
    position: absolute;
    width: 100%;
    height: 4px;
    border-radius: 4px;
    background-color: #18272F;
    bottom: 0;
    left: 0;
    transform-origin: right;
    transform: scaleX(0);
    transition: transform .3s ease-in-out;
  }

a:hover::before {
  transform-origin: left;
  transform: scaleX(1);
}

That’s not the only way to accomplish this! Here’s another one by Justin Wong using background instead:

Geoff also has a roundup of CSS link hover effects, ranging from neat to downright absurd. Worth checking out!

Have a blast linking!

There are a lot of options when it comes to creating your own hover effect for in-line links with CSS. You can even play with these effects and create something new. I hope you liked the article. Keep experimenting!


6 Creative Ideas for CSS Link Hover Effects originally published on CSS-Tricks. You should get the newsletter.

Adam Argyle’s Sick Mouse-Out CSS Hover Effect

I was killing some time browsing my CodePen feed for some eye candy and didn’t need to go past the first page before spotting a neat CSS hover effect by Adam Argyle.

I must’ve spent 10 minutes just staring at the demo in awe. There’s something about this that feels so app-like. I think it might be how contextually accurate it is in that the background color slides in from the left, then exits out through the right. It’s exactly the sort of behavior I’d expect from a mouse-in, mouse-out sort of interaction.

Whatever the case, I fired up a fresh pen and went to work recreating it. And it’s not super complex or anything, but rather a clever use of transitions and transforms paired with proper offsets. Quite elegant! I’m actually a little embarrassed how long it took me to realize how the mouse-out part works.

Here’s how I tackled it, warts and all.

“I bet that’s using a transition on a background.”

That was my first thought. Define the background-color, set the background-size and background-position, then transition the background-position. That’s how I’ve seen that “growing” background color thing done in the past. I’ve done that myself on some projects, like this:

If I could do the same thing, only from left-to-right, then all that’s left is the mouse-out, right? Nope. The problem is there’s nothing that can really make the background-position transition from left-to-right to left-to-right. I could make it do one or the other, but not both.

“Maybe it’s a transform instead.”

My next attempt was jump into transforms. The transform property provides a bunch of functions that can transition together for slightly more complex movement. For example, the background can “grow” or “shrink” by changing the element’s scale(). Or, in this case, just along the x-axis with scaleX().

But like I mentioned, there isn’t a way to isolate the element’s background to do that. Going from scaleX(0) to scaleX(1) scales the entire element, so that basically squishes the link — content and all — down to nothing, then stretches it back out to its natural size which is a totally different effect. Plus, it means starting with scaleX(0) which hides the whole dang thing by default making it unusable.

But a pseudo-element could work! It doesn’t matter if that gets squished or hidden because it isn’t part of the actual content. Gotta put the background on that instead and position it directly under the link.

a {
  /* Keeps the pseudo-element contained to the element */
  position: relative;
}

a::before {
  background: #ff9800;
  content: "";
  inset: 0; /* Logical equivalent to physical offsets */
  position: absolute;
  transform: scaleX(0); /* Hide by default */
  z-index: -1; /* Ensures the link is stacked on top */
}

“Now I need ::before to change on hover.”

I knew I could make ::before scale from 0 to 1 by chaining it to the link element’s :hover state.

a:hover::before {
  transform: scaleX(1)
}

Nice! I was onto something.

Sprinkle a little transition fairy dust on it and things start to come to life.

a::before {
  background: #ff9800;
  content: "";
  inset: 0;
  position: absolute;
  transform: scaleX(0);
  transition: transform .5s ease-in-out;
  z-index: -1;
}

“Hmm, the transition moves in both directions.”

Again, this is where I sorta got stuck. Something in my head just wasn’t clicking for some reason. As per usual, I ran over to the CSS-Tricks Almanac to see what property might’ve slipped my mind.

Ah, yes. That would be transform-origin. That allows me to set where the transform starts, which is not totally dissimilar from setting the background-position like I tried earlier. The transform could start from the left instead of its default 50% 50% position.

a::before {
  background: #ff9800;
  content: "";
  inset: 0;
  position: absolute;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .5s ease-in-out;
  z-index: -1;
}

Yeah, like this:

I was already transitioning ::before to scaleX(1) on link hover. If I reversed the transform-origin from left to right at the same time, then mayyyybe the highlight goes out the opposite of how it came in when the mouse exits?

a:hover::before {
  transform: scaleX(1);
  transform-origin: right;
}

🤞

Whoops, backwards! Let’s swap the left and right values. 🙃

Gorgeous. Thank you, Adam, for the inspiration!


Adam Argyle’s Sick Mouse-Out CSS Hover Effect originally published on CSS-Tricks. You should get the newsletter and become a supporter.

CSS Underlines Are Too Thin and Too Low in Chrome

I’ve encountered two bugs in Chrome while testing the new CSS text-decoration-thickness and text-underline-offset properties, and I want to share them with you here in this article.

But first, let’s acknowledge one thing:

Default underlines are inconsistent

Let’s add a text link to a plain web page, set its font-family to Arial, and compare the underlines across browsers and operating systems.

From left to right: Chrome, Safari, and Firefox on macOS; Safari on iOS; Chrome, and Firefox on Windows; Chrome, and Firefox on Android.

As you can see, the default underline is inconsistent across browsers. Each browser chooses their own default thickness and vertical position (offset from the baseline) for the underline. This is in line with the CSS Text Decoration module, which specifies the following default behavior (auto value):

The user agent chooses an appropriate thickness for text decoration lines. […] The user agent chooses an appropriate offset for underlines.

Luckily, we can override the browsers’ defaults

There are two new, widely supported CSS properties that allow us to precisely define the thickness and offset for our underlines:

With these properties, we can create consistent underlines even across two very different browsers, such as the Gecko-based Firefox on Android and the WebKit-based Safari on macOS.

h1 {
  text-decoration: underline;
  text-decoration-thickness: 0.04em;
  text-underline-offset: 0.03em;
}
Top row: the browsers’ default underlines; bottom row: consistent underlines with CSS. (Demo)

Note: The text-decoration-thickness property also has a special from-font value that instructs browsers to use the font’s own preferred underline width, if available. I tested this value with a few different fonts, but the underlines were inconsistent.

OK, so let’s move on to the two Chrome bugs I noted earlier.

Chrome bug 1: Underlines are too thin on macOS

If you set the text-decoration-thickness property to a font-relative length value that computes to a non-integer pixel value, Chrome will “floor” that value instead of rounding it to the nearest integer. For example, if the declared thickness is 0.06em, and that computes to 1.92px, Chrome will paint a thickness of 1px instead of 2px. This issue is limited to macOS.

a {
  font-size: 2em; /* computes to 32px */
  text-decoration-thickness: 0.06em; /* computes to 1.92px */
}

In the following screenshot, notice how the text decoration lines are twice as thin in Chrome (third row) than in Safari and Firefox.

From top to bottom: Safari, Firefox, and Chrome on macOS. (Demo)

For more information about this bug, see Chromium issue #1255280.

Chrome bug 2: Underlines are too low

The text-underline-offset property allows us to precisely set the distance between the alphabetic baseline and the underline (the underline’s offset from the baseline). Unfortunately, this feature is currently not implemented correctly in Chrome and, as a result, the underline is positioned too low.

h1 {
  text-decoration: underline;
  text-decoration-color: #f707;

  /* disable “skip ink” */
  -webkit-text-decoration-skip: none; /* Safari */
  text-decoration-skip-ink: none;

  /* cover the entire descender */
  text-decoration-thickness: 0.175em; /* descender height */
  text-underline-offset: 0; /* no offset from baseline */
}

Because of this bug, it is not possible to move the underline all the way up to the baseline in Chrome.

From left to right: Safari, Firefox, and Chrome on macOS. View this demo on CodePen.

For more information about this bug, see Chromium issue #1172623.

Note: As you might have noticed from the image above, Safari draws underlines on top of descenders instead of beneath them. This is a WebKit bug that was fixed very recently. The fix should ship in the next version of Safari.

Help prioritize the Chrome bugs

The two new CSS properties for styling underlines are a welcome addition to CSS. Hopefully, the two related Chrome bugs will be fixed sooner rather than later. If these CSS features are important to you, make your voice heard by starring the bugs in Chromium’s bug tracker.

Sign in with your Google account and click the star button on issues #1172623 and #1255280.

CSS Underlines Are Too Thin and Too Low in Chrome originally published on CSS-Tricks

Buttons vs. Links

There are thousands of articles out there about buttons and links on the web; the differences and how to use them properly. Hey, I don’t mind. I wrote my own as well¹.

It’s such a common mistake on the web that it’s always worth repeating:

  • Is the intention to send someone to another URL? It’s a link in the form of <a href="">.
  • Is it to trigger some on-page interactivity? It’s a button in the form of <button>.
  • Any devition from from those and you better smurfing know what you are doing.

Eric Eggert wrote a pretty good piece recently with a nice line about why it matters:

If you had a keyboard and your “e” key would only work 90% of the time, it would be infuriating. Reliability and trust in user interfaces is important to allow users to navigate content and application with ease. If you use the right elements, you support users.

Manuel Matuzović has a Button Cheat Sheet that is a lol-inducing ride about why literally everything other than a <button> isn’t as good as a button. Manuel links up Marcy Sutton’s epic The Links vs. Buttons Showdown (video), pitting the two against each other in a mock battle — “We’ll pit two HTML elements against each other in a crusade of better and worse, right and possible wrong. One element is triggered with the space bar, the other with the enter key. Who will win?” I don’t know whether to laugh or cry at how far we have to go to spread this information.

  1. I think our article A Complete Guide to Links and Buttons is a pretty good example of beginner-oriented content, which is my favorite style of content to write and publish! But because there is so much beginner-oriented content on the web, the bar is pretty high if you want to make and impact and get enough SEO for anyone to even ever find it. So, in this case, the idea was to go big and write nearly as much as there is to write about the technical foundation of links and buttons. If you’ve got a knack for this kind of writing, reach out for sure.


The post Buttons vs. Links appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

target=blank

Does that make your eye twitch a little bit? Like… it’s a typo. It should be target="_blank" with an underscore to start the value. As in…

<a target="_blank" href="https://codepen.io">
  Open CodePen in a New Tab
</a>

Welp, that’s correct syntax!

In the case of the no-underscore target="blank", the blank part is just a name. It could be anything. It could be target="foo" or, perhaps to foreshadow the purpose here: target="open-new-links-in-this-space".

The difference:

  • target="_blank" is a special keyword that will open links in a new tab every time.
  • target="blank" will open the first-clicked link in a new tab, but any future links that share target="blank" will open in that same newly-opened tab.

I never knew this! I credit this tweet explanation.

I created a very basic demo page to show off the functionality (code). Watch as a new tab opens when I click the first link. Then, subsequent clicks from either also open tab open that link in that new second tab.

Why?

I think use cases here are few and far between. Heck, I’m not even that big of a fan of target="_blank". But here’s one I could imagine: documentation.

Say you’ve got a web app where people actively do work. It might make sense to open links to documentation from within that app in a new tab, so they aren’t navigating away from active work. But, maybe you think they don’t need a new tab for every documentation link. You could do like…

<a target="codepen-documentation" 
  href="https://blog.codepen.io/documentation/">
  View CodePen Documentation
</a> 

<!-- elsewhere -->

<a target="codepen-documentation" 
  href="https://blog.codepen.io/documentation/">
  About Asset Hosting
</a>

The post target=blank appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.