TasteWP FTW

TasteWP enables anyone to setup a test/temporary WordPress instance in seconds. So you can play around and do things like test plugins on a live site. I know this kind of thing has been done before, but I've never seen it made SO EASY. Like stupid easy. And FREE. Awesome tool.

Direct link to article | View post at DigWP.com

Create a Tag Cloud with some Simple CSS and even Simpler JavaScript

I’ve always liked tag clouds. I like the UX of seeing what tags are most popular on a website by seeing the relative font size of the tags, popular tags being bigger. They seem to have fallen out of fashion, though you do often see versions of them used in illustrations in tools like Wordle.

How difficult is it to make a tag cloud? Not very difficult at all. Let’s see!

Let’s start with the markup

For our HTML, we’re going to put each of our tags into a list, <ul class="tags"><ul>. We’ll be injecting into that with JavaScript.

If your tag cloud is already in HTML, and you are just looking to do the relative font-size thing, that’s good! Progressive enhancement! You should be able to adapt the JavaScript later on so it does just that part, but not necessarily building and injecting the tags themselves.

I have mocked out some JSON with a certain amount of articles tagged with each property. Let’s write some JavaScript to go grab that JSON feed and do three things.

First, we’ll create an <li> from each entry for our list. Imagine the HTML, so far, is like this:

<ul class="tags">
  <li>align-content</li>
  <li>align-items</li>
  <li>align-self</li>
  <li>animation</li>
  <li>...</li>
  <li>z-index</li>
</ul>

Second, we’ll put the number of articles each property has in parentheses beside inside each list item. So now, the markup is like this:

<ul class="tags">
  <li>align-content (2)</li>
  <li>align-items (2)</li>
  <li>align-self (2)</li>
  <li>animation (9)</li>
  <li>...</li>
  <li>z-index (4)</li>
</ul>

Third, and last, we’ll create a link around each tag that goes to the correct place. This is where we can set the font-size property for each item depending on how many articles that property is tagged with, so animation that has 13 articles will be much bigger than background-color which only has one article.

<li class="tag">
  <a
    class="tag__link"
    href="https://example.com/tags/animation"
    style="font-size: 5em">
    animation (9)
  </a>
</li>

The JavasScript part

Let’s have a look at the JavaScript to do this.

const dataURL =
  "https://gist.githubusercontent.com/markconroy/536228ed416a551de8852b74615e55dd/raw/9b96c9049b10e7e18ee922b4caf9167acb4efdd6/tags.json";
const tags = document.querySelector(".tags");
const fragment = document.createDocumentFragment();
const maxFontSizeForTag = 6;

fetch(dataURL)
  .then(function (res) {
    return res.json();
  })
  .then(function (data) {
    // 1. Create a new array from data
    let orderedData = data.map((x) => x);
    // 2. Order it by number of articles each tag has
    orderedData.sort(function(a, b) {
      return a.tagged_articles.length - b.tagged_articles.length;
    });
    orderedData = orderedData.reverse();
    // 3. Get a value for the tag with the most articles
    const highestValue = orderedData[0].tagged_articles.length;
    // 4. Create a list item for each result from data.
    data.forEach((result) => handleResult(result, highestValue));
    // 5. Append the full list of tags to the tags element
    tags.appendChild(tag);
  });

The JavaScript above uses the Fetch API to fetch the URL where tags.json is hosted. Once it gets this data, it returns it as JSON. Here we seque into a new array called orderedData (so we don’t mutate the original array), find the tag with the most articles. We’ll use this value later on in a font-scale so all other tags will have a font-size relative to it. Then, forEach result in the response, we call a function I have named handleResult() and pass the result and the highestValue to this function as a parameter. It also creates:

  • a variable called tags which is what we will use to inject each list item that we create from the results,
  • a variable for a fragment to hold the result of each iteration of the loop, which we will later append to the tags, and
  • a variable for the max font size, which we’ll use in our font scale later.

Next up, the handleResult(result) function:

function handleResult(result, highestValue) {
  const tag = document.createElement("li");
  tag.classList.add("tag");
  tag.innerHTML = `<a class="tag__link" href="${result.href}" style="font-size: ${result.tagged_articles.length * 1.25}em">${result.title} (${result.tagged_articles.length})</a>`;

  // Append each tag to the fragment
  fragment.appendChild(tag);
}

This is pretty simple function that creates a list element set to the variable named tag and then adds a .tag class to this list element. Once that’s created, it sets the innerHTML of the list item to be a link and populates the values of that link with values from the JSON feed, such as a result.href for the link to the tag. When each li is created, it’s then added as a string to the fragment, which we will later then append to the tags variable. The most important item here is the inline style tag that uses the number of articles—result.tagged_articles.length—to set a relative font size using em units for this list item. Later, we’ll change that value to a formula to use a basic font scale.

I find this JavaScript just a little bit ugly and hard on the eyes, so let’s create some variables and a simple font scale formula for each of our properties to tidy it up and make it easier to read.

function handleResult(result, highestValue) {
  // Set our variables
  const name = result.title;
  const link = result.href;
  const numberOfArticles = result.tagged_articles.length;
  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;
  fontSize = +fontSize.toFixed(2);
  const fontSizeProperty = `${fontSize}em`;

  // Create a list element for each tag and inline the font size
  const tag = document.createElement("li");
  tag.classList.add("tag");
  tag.innerHTML = `<a class="tag__link" href="${link}" style="font-size: ${fontSizeProperty}">${name} (${numberOfArticles})</a>`;
  
  // Append each tag to the fragment
  fragment.appendChild(tag);
}

By setting some variables before we get into creating our HTML, the code is a lot easier to read. And it also makes our code a little bit more DRY, as we can use the numberOfArticles variable in more than one place.

Once each of the tags has been returned in this .forEach loop, they are collected together in the fragment. After that, we use appendChild() to add them to the tags element. This means the DOM is manipulated only once, instead of being manipulated each time the loop runs, which is a nice performance boost if we happen to have a large number of tags.

Font scaling

What we have now will work fine for us, and we could start writing our CSS. However, our formula for the fontSize variable means that the tag with the most articles (which is “flex” with 25) will be 6em (25 / 25 * 6 = 6), but the tags with only one article are going to be 1/25th the size of that (1 / 25 * 6 = 0.24), making the content unreadable. If we had a tag with 100 articles, the smaller tags would fare even worse (1 / 100 * 6 = 0.06).

To get around this, I have added a simple if statement that if the fontSize that is returned is less than 1, set the fontSize to 1. If not, keep it at its current size. Now, all the tags will be within a font scale of 1em to 6em, rounded off to two decimal places. To increase the size of the largest tag, just change the value of maxFontSizeForTag. You can decide what works best for you based on the amount of content you are dealing with.

function handleResult(result, highestValue) {
  // Set our variables
  const numberOfArticles = result.tagged_articles.length;
  const name = result.title;
  const link = result.href;
  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;
  fontSize = +fontSize.toFixed(2);
  
  // Make sure our font size will be at least 1em
  if (fontSize <= 1) {
    fontSize = 1;
  } else {
    fontSize = fontSize;
  }
  const fontSizeProperty = `${fontSize}em`;
  
  // Then, create a list element for each tag and inline the font size.
  tag = document.createElement("li");
  tag.classList.add("tag");
  tag.innerHTML = `<a class="tag__link" href="${link}" style="font-size: ${fontSizeProperty}">${name} (${numberOfArticles})</a>`;

  // Append each tag to the fragment
  fragment.appendChild(tag);
}

Now the CSS!

We’re using flexbox for our layout since each of the tags can be of varying width. We then center-align them with justify-content: center, and remove the list bullets.

.tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 960px;
  margin: auto;
  padding: 2rem 0 1rem;
  list-style: none;
  border: 2px solid white;
  border-radius: 5px;
}

We’ll also use flexbox for the individual tags. This allows us to vertically align them with align-items: center since they will have varying heights based on their font sizes.

.tag {
  display: flex;
  align-items: center;
  margin: 0.25rem 1rem;
}

Each link in the tag cloud has a small bit of padding, just to allow it to be clickable slightly outside of its strict dimensions.

.tag__link {
  padding: 5px 5px 0;
  transition: 0.3s;
  text-decoration: none;
}

I find this is handy on small screens especially for people who might find it harder to tap on links. The initial text-decoration is removed as I think we can assume each item of text in the tag cloud is a link and so a special decoration is not needed for them.

I’ll just drop in some colors to style things up a bit more:

.tag:nth-of-type(4n+1) .tag__link {
  color: #ffd560;
}
.tag:nth-of-type(4n+2) .tag__link {
  color: #ee4266;
}
.tag:nth-of-type(4n+3) .tag__link {
  color: #9e88f7;
}
.tag:nth-of-type(4n+4) .tag__link {
  color: #54d0ff;
}

The color scheme for this was stolen directly from Chris’ blogroll, where every fourth tag starting at tag one is yellow, every fourth tag starting at tag two is red, every fourth tag starting at tag three is purple. and every fourth tag starting at tag four is blue.

Screenshot of the blogroll on Chris Coyier's personal website, showing lots of brightly colored links with the names of blogs included in the blogroll.

We then set the focus and hover states for each link:

.tag:nth-of-type(4n+1) .tag__link:focus,
.tag:nth-of-type(4n+1) .tag__link:hover {
  box-shadow: inset 0 -1.3em 0 0 #ffd560;
}
.tag:nth-of-type(4n+2) .tag__link:focus,
.tag:nth-of-type(4n+2) .tag__link:hover {
  box-shadow: inset 0 -1.3em 0 0 #ee4266;
}
.tag:nth-of-type(4n+3) .tag__link:focus,
.tag:nth-of-type(4n+3) .tag__link:hover {
  box-shadow: inset 0 -1.3em 0 0 #9e88f7;
}
.tag:nth-of-type(4n+4) .tag__link:focus,
.tag:nth-of-type(4n+4) .tag__link:hover {
  box-shadow: inset 0 -1.3em 0 0 #54d0ff;
}

I could probably have created a custom variable for the colors at this stage—like --yellow: #ffd560, etc.—but decided to go with the longhand approach for IE 11 support. I love the box-shadow hover effect. It’s a very small amount of code to achieve something much more visually-appealing than a standard underline or bottom-border. Using em units here means we have decent control over how large the shadow would be in relation to the text it needed to cover.

OK, let’s top this off by setting every tag link to be black on hover:

.tag:nth-of-type(4n+1) .tag__link:focus,
.tag:nth-of-type(4n+1) .tag__link:hover,
.tag:nth-of-type(4n+2) .tag__link:focus,
.tag:nth-of-type(4n+2) .tag__link:hover,
.tag:nth-of-type(4n+3) .tag__link:focus,
.tag:nth-of-type(4n+3) .tag__link:hover,
.tag:nth-of-type(4n+4) .tag__link:focus,
.tag:nth-of-type(4n+4) .tag__link:hover {
  color: black;
}

And we’re done! Here’s the final result:


The post Create a Tag Cloud with some Simple CSS and even Simpler JavaScript appeared first on CSS-Tricks.

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

A CSS-only, animated, wrapping underline

Nicky Meuleman, inspired by Cassie Evans, details how they built the anchor link hover on their sites. When a link is hovered, another color underline kinda slides in with a gap between the two. Typical text-decoration doesn’t help here, so multiple backgrounds are used instead, and fortunately, it works with text that breaks across multiple lines as well.

Direct Link to ArticlePermalink


The post A CSS-only, animated, wrapping underline appeared first on CSS-Tricks.

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

Block Links: The Search for a Perfect Solution

I was reading this article by Chris where he talks about block links — you know, like wrapping an entire card element inside an anchor — being a bad idea. It’s bad accessibility because of how it affects screen readers. And it’s bad UX because it prevents simple user tasks, like selecting text.

But maybe there’s something else at play. Maybe it’s less an issue with the pattern than the implementation of it. That led me to believe that this is the time to write follow-up article to see if we can address some of the problems Chris pointed out.

Throughout this post, I’ll use the term “card” to describe a component using the block link pattern. Here’s what we mean by that.

Let’s see how we want our Card Components to work:

  1. The whole thing should be linked and clickable.
  2. It should be able to contain more than one link.
  3. Content should be semantic so assistive tech can understand it.
  4. The text should be selectable, like regular links.
  5. Things like right-click and keyboard shortcuts should work with it
  6. Its elements should be focusable when tabbing.

That’s a long list! And since we don’t have any standard card widget provided by the browser, we don’t have any standard guidelines to build it. 

Like most things on the web, there’s more than one way to make a card component. However, I haven’t found something that checks all the requirements we just covered. In this article, we will try to hit all of them. That’s what we’re going to do now!

Method 1: Wrap everything an <a>

This is the most common and the easiest way to make a linked card. Take the HTML for the card and wrap the entire thing in an anchor tag.

<a href="/">
  <!-- Card markup -->
</a>

Here’s what that gives us:

  1. It’s clickable.
  2. It works with right-click and keyboard shortcuts.

Well, not great. We still can’t:

  1. Put another link inside the card because the entire thing is a single link
  2. Use it with a screen reader — the content is not semantic, so assistive technology will announce everything inside the card, starting from the time stamp
  3. Select text

That’s enough 👎 that we probably shouldn’t use it. Let’s move onto the next technique.

Method 2: Just link what needs linking

This is a nice compromise that sacrifices a little UX for improved accessibility.

With this pattern we achieve most of our goals:

  1. We can put as many links as we want. 
  2. Content is semantic.
  3. We can select the text from Card.
  4. Right Click and keyboard shortcuts work.
  5. The focus is in proper order when tabbing.

But it is missing the main feature we want in a card: the whole thing should be clickable! Looks like we need to try some other way.

Method 3: The good ol’  ::before pseudo element

In this one, we add a ::before or ::after element, place it above the card with absolute positioning and stretch it over the entire width and height of the card so it’s clickable.

But now:

  1. We still can’t add more than one link because anything else that’s linked is under the pseudo element layer. We can try to put all the text above the pseudo element, but card link itself won’t work when clicking on top of the text.
  2. We still can’t select the text. Again, we could swap layers, but then we’re back to the clickable link issue all over again.

Let’s try to actually check all the boxes here in our final technique.

Method 4: Sprinkle JavaScript on the second method

Let’s build off the second method. Recall that’s what where we link up everything we want to be a link:

<article class="card">
  <time datetime="2020-03-20">Mar 20, 2020</time>
  <h2><a href="https://css-tricks.com/a-complete-guide-to-calc-in-css/" class="main-link">A Complete Guide to calc() in CSS</a></h2>
  <p>
    In this guide, let’s cover just about everything there is to know about this very useful function.
  </p>
  <a class="author-name" href="https://css-tricks.com/author/chriscoyier/" target="_blank">Chris Coyier</a>
    <div class="tags">
      <a class="tag" href="https://css-tricks.com/tag/calc/" >calc</a>
    </div>
</article>

So how do we make the whole card clickable? We could use JavaScript as a progressive enhancement to do that. We’ll start by adding a click event listener to the card and trigger the click on the main link when it is triggered.

const card = document.querySelector(".card")
const mainLink = document.querySelector('.main-link')


card.addEventListener("click", handleClick)


function handleClick(event) {
  mainLink.click();
}

Temporarily, this introduces the problem that we can’t select the text, which we’ve been trying to fix this whole time. Here’s the trick: we’ll use the relatively less-known web API window.getSelection. From MDN:

The Window.getSelection() method returns a Selection object representing the range of text selected by the user or the current position of the caret.

Although, this method returns an Object, we can convert it to a string with toString().

const isTextSelected = window.getSelection().toString()

With one line and no complicated kung-fu tricks with event listeners, we know if the user has selected text. Let’s use that in our handleClick function.

const card = document.querySelector(".card")
const mainLink = document.querySelector('.main-link')


card.addEventListener("click", handleClick)


function handleClick(event) {
  const isTextSelected = window.getSelection().toString();
  if (!isTextSelected) {
    mainLink.click();
  }
}

This way, the main link can be clicked when no text selected, and all it took was a few lines of JavaScript. This satisfies our requirements:

  1. The whole thing is linked and clickable.
  2. It is able to contain more than one link.
  3. This content is semantic so assistive tech can understand it.
  4. The text should be selectable, like regular links.
  5. Things like right-click and keyboard shortcuts should work with it
  6. Its elements should be focusable when tabbing.

We have satisfied all the requirements but there are still some gotchas, like double event triggering on clickable elements like links and buttons in the card. We can fix this by adding a click event listener on all of them and stopping the propagation of event.

// You might want to add common class like 'clickable' on all elements and use that for the query selector.
const clickableElements = Array.from(card.querySelectorAll("a"));
clickableElements.forEach((ele) =>
ele.addEventListener("click", (e) => e.stopPropagation())
);

Here’s the final demo with all the JavaScript code we have added:

I think we’ve done it! Now you know how to make a perfect clickable card component.

What about other patterns? For example, what if the card contains the excerpt of a blog post followed by a “Read More’ link? Where should that go? Does that become the “main” link? What about image?

For those questions and more, here’s some further reading on the topic:

The post Block Links: The Search for a Perfect Solution appeared first on CSS-Tricks.

The Contrast Triangle

Chip Cullen:

Let’s say you’re building a site, and you’re working with a designer. They come to you with some solid designs, and you’re ready to go. You’re also a conscientious front end developer and you like to make sure the sites you build are accessible. The designs you’re working from have some body copy, but you notice that the links inside the body copy are missing underlines.

You are now in The Contrast Triangle.

The “triangle” meaning a three-sided comparison:

  • The contrast between the background and text
  • The contrast between the background and links
  • the contrast between text and links

I would think this matters whether you underline links or not, but I take the point that without underlines the problem is worse.

I’d also argue the problem is even more complicated. You’ve also got to consider the text when it is selected, and make sure everything has contrast when that is the case too. And the hover states, active states, visited states, and focus states. So it’s really like hexacontakaienneagon of contrast or something.

Direct Link to ArticlePermalink

The post The Contrast Triangle appeared first on CSS-Tricks.

View Custom Fields Meta Box in Gutenberg Block Editor

I get bunches of emails asking what happened to the "Custom Fields" meta box on the "Edit Posts" screen. They're hidden by default with the new Block Editor, so questions like, "do I need to install a plugin to get them back again?" No you don't. To view the Custom Fields for any post click the three dots in the upper-right corner of the screen, and then go to Options. There you will find a checkbox to enable Custom Fields (under "Advanced Panels"). Scroll down the page and you will see the Custom Fields meta box.

Direct link to article | View post at DigWP.com

How to Create a “Skip to Content” Link

Skip links are little internal navigation links that help users move around a page. It’s possible you’ve never actually seen one before because they’re often hidden from view and used as an accessibility enhancement that lets keyboard users and screen readers jump from the top of the page to the content without have to go through other elements on the page first.

In fact, you can find one right here on CSS-Tricks if you crack DevTools open.

In my opinion, the best way to implement a skip link is to hide it and then bring it into view when it is focused. So, let’s say we have a link in the HTML:

<a class="skip-to-content-link" href="#main">
  Skip to content
</a>

…we can give it an absolute position and translate it off the screen:

.skip-to-content-link {
  left: 50%;
  position: absolute;
  transform: translateY(-100%);
}

Then we can bring it back into view when it’s in focus and style it up a bit in the process:

.skip-to-content-link {
  background: #e77e23;
  height: 30px;
  left: 50%;
  padding: 8px;
  position: absolute;
  transform: translateY(-100%);
  transition: transform 0.3s;
}

.skip-to-content-link:focus {
  transform: translateY(0%);
}

This will hide our link until it is focused and then put it into view when it becomes focused.

Now, allow me to elaborate, starting with this quote from Miles Davis:

Time isn’t the main thing. It’s the only thing.

As I sit down to write this article in a rainy Ireland, I think of the challenge that many users face as they use the web that I take for granted. We put so much thought into creating a great user experience without thinking of all our users and how to meet their needs. Admittedly, a skip link was something I had never heard of until completing a course on Frontend Masters by Marcy Sutton. Since learning the power and simplicity of using a skip link, I decided to make it my mission to spread more awareness — and what platform better than CSS-Tricks!

A solution is an answer to a problem, so what’s the solution for helping keyboard users and screen readers find the content of a page quickly? In short, the solution is time. Giving users the ability to navigate to parts of our website that they are most interested in gives them the power to save valuable time.

Take the Sky News website as an example. It offers a “Skip to content” button that allows users to skip all the navigation items and jump straight to the main content.

You can see this button by navigating to the top of the page using your keyboard.  This is similar to the implementation shown above. The link is always in the document but only becomes visible when it’s in focus.

This is the type of skip link we are going to create together in this post.

Our sample website

I built a sample website that we will use to demonstrate a skip link.

The website has a number of navigation links but, in the interest of time, there are only two pages: the home page and the blog page. This is all we need to see how things work.

Identifying the problem

Here’s the navigation we’re working with:

In total, we have eight navigation items that a keyboard user and screen reader must tab through before reaching the main content below the navigation.

That’s the problem. The navigation may be irrelevant for the user. Perhaps the user was given a direct link to an article and they simply want to get to the content.

This is a perfect use case for a skip link.

Creating the link

There are a couple of approaches to creating a Skip to content link.  What I like to do is similar to the Sky News example, which is hiding the link until it is focused.  That means we can drop the link at or near the top of the page, like inside the <header> element.

<header>
  <a class="skip-link" href='#main'>Skip to content</a>
  <!-- Navigation-->
</header>

This link has a .skip-link class so we can style it. Thehref attribute points to #main, which is the ID we will add to the <main> element that comes further down the page. That’s what the link will jump to when clicked.

<header>
  <a class="skip-link" href='#main'>Skip to content</a>
  <!-- Navigation-->
</header>


<!-- Maybe some other stuff... -->


<main id="main">
  <!-- Content -->
</main>

Here’s what we have if we simply drop the link into the header with no styling.

This does not look great, but the functionality is there. Try navigating to the link with your keyboard and pressing Enter when it’s in focus.

Now it’s time to make it look pretty. We must first fix the positioning and only show our skip link when it is in focus.

.skip-link {
  background: #319795;
  color: #fff;
  font-weight: 700;
  left: 50%;
  padding: 4px;
  position: absolute;
  transform: translateY(-100%);
}

.skip-link:focus {
  transform: translateY(0%);
}

The magic here is in the transform property, which is hiding and showing our skip link depending on whether it is focused or not. Let’s make it look a little nicer with a quick transition on the transform property.

.skip-link {
  /* Same as  before */
  transition: transform 0.3s;
}

It will now transition into view which makes that bit better.

You should now (hopefully) have what I have below:

As you can see, the skip link bypasses the navigation and jumps straight down to the <main> element when clicked.

It’s OK to use more than one link!

Right now, the link only serves one purpose and that is skip to the content of our website. But we don’t have to stop there.

We can go even further and create a skip link that has more options, such as a way to jump to the footer of the site. As you might imagine, this is quite similar to what we’ve already done.

Let’s make the blog page of the example site a little more usable by using multiple skip links. It’s common for blogs to use AJAX that loads in more posts when reaching the bottom of the page. This can make it very difficult to get to the footer of the website. That’s the problem we want to solve in this case.

So let’s add a second link that bypasses all that auto-loading business and jumps the user straight to a #footer element on the page.

<div class="skip-link" >
  Skip to <a href='#main'>content</a> or <a href='#footer'>footer</a>
</div>

We also need to amend our CSS a little and use the :focus-within pseudo selector.

.skip-link {
  transform: translateY(-100%);
}

.skip-link:focus-within {
  transform: translateY(0%);
}

This is saying if anything within our .skip-link element has focus, then we show it. Sadly, neither Internet Explorer nor Opera Mini support focus-within, but its coverage is pretty darn good and there is a polyfill available.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
6052No7910.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
8068No10.3

Last thing we need to do is make sure there's an ID on our footer element so the link has something to jump to.

<footer id="footer">

Here's what this gives us:

If we wanted to go one step further (and I’d encourage it), we could style each link a little differently so users can distinguish between the two. Both links in this example are plain white which works great for a single button that does a single thing, but it’d be clearer that we’re dealing with two links if they were presented differently.

Jumping to conclusions

Are you using skip links on your site? Or, if not, does this convince you to use one? I hope it’s clear that skip links are a great value add when it comes to the accessibility of a site. While it’s not a silver bullet that solves every accessibility need, it does solve some use cases that make for a much more polished user experience.

Here are some prominent sites that are using this or a similar technique:

The post How to Create a “Skip to Content” Link appeared first on CSS-Tricks.

Use a:visited in your CSS stylesheet

Evert Pot:

Unfortunately, when setting a new color (e.g. a { color: #44F }) the ‘purple visited link’ feature also gets disabled. I think this is a shame, as there’s so many instances where you’re going through a list of links and want to see what you’ve seen before.

The 2 examples I ran into today were:

• AWS Cloudwatch Logs
• Stackoverflow search results

I like those use cases. My take is that :visited is perhaps a bit under-used in general, but not by much. It's useful in that situation where a user might wonder: hmmmm, have I seen this one yet?

I'm not particularly compelled to use it on this site — as I'm not convinced it matters for the UX if you've visited any particular link, particularly not in a blog-like setting as here.

Direct Link to ArticlePermalink

The post Use a:visited in your CSS stylesheet appeared first on CSS-Tricks.

4 Ways to Animate the Color of a Text Link on Hover

Let’s create a pure CSS effect that changes the color of a text link on hover… but slide that new color in instead of simply swapping colors.

There are four different techniques we can use to do this. Let’s look at those while being mindful of important things, like accessibility, performance, and browser support in mind.

Let’s get started!

Technique 1: Using background-clip: text

At the time of writing, the background-clip: text property is an experimental feature and is not supported in Internet Explorer 11 and below.

This technique involves creating knockout text with a hard stop gradient. The markup consists of a single HTML link (<a>) element to create a hyperlink:

<a href="#">Link Hover</a>

We can start adding styles to the hyperlink. Using overflow: hidden will clip any content outside of the hyperlink during the hover transition:

a {
  position: relative;
  display: inline-block;
  font-size: 2em;
  font-weight: 800;
  color: royalblue;
  overflow: hidden;
}

We will need to use a linear gradient with a hard stop at 50% to the starting color we want the link to be as well as the color that it will change to:

a {
  /* Same as before */
  background: linear-gradient(to right, midnightblue, midnightblue 50%, royalblue 50%);
}

Let’s use background-clip to clip the gradient and the text value to display the text. We will also use the background-size and background-position properties to have the starting color appear:

a {
  /* Same as before */
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-size: 200% 100%;
  background-position: 100%;
}

Finally, let’s add the transition CSS property and :hover CSS pseudo-class to the hyperlink. To have the link fill from left to right on hover, use the background-position property:

a {
  /* Same as before */
  transition: background-position 275ms ease;
}
a:hover {
  background-position: 0 100%;
}

While this technique does achieve the hover effect, Safari and Chrome will clip text decorations and shadows, meaning they won’t be displayed. Applying text styles, such as an underline, with the text-decoration CSS property will not work. Perhaps consider using other approaches when creating underlines.

Technique 2: Using width/height

This works by using a data attribute containing the same text as the one in the <a> tag and setting the width (filling the text from left-to-right or right-to-left) or height (filling the text from top-to-bottom or bottom-to-top), from 0% to 100% on hover.

Here is the markup:

<a href="#" data-content="Link Hover">Link Hover</a>

The CSS is similar to the previous technique minus the background CSS properties. The text-decoration property will work here:

a {
  position: relative;
  display: inline-block;
  font-size: 2em;
  color: royalblue;
  font-weight: 800;
  text-decoration: underline;
  overflow: hidden;
}

This is when we need to use the content from the data-content attribute. It will be positioned above the content in the <a> tag. We get to use the nice little trick of copying the text in the data attribute and displaying it via the attr() function on the content property of the element’s ::before pseudo-element.

a::before {
  position: absolute;
  content: attr(data-content); /* Prints the value of the attribute */
  top: 0;
  left: 0;
  color: midnightblue;
  text-decoration: underline;
  overflow: hidden;
  transition: width 275ms ease;
}

To keep the text from wrapping to the next line, white-space: nowrap will be applied. To change the link fill color, set the value for the color CSS property using the ::before pseudo-element and having the width start at 0:

a::before {
  /* Same as before */
  width: 0;
  white-space: nowrap;
}

Increase the width to 100% to the ::before pseudo element to complete the text effect on hover:

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

While this technique does the trick, using the width or height properties will not produce a performant CSS transition. It is best to use either the transform or opacity properties to achieve a smooth, 60fps transition.

Using the text-decoration CSS property can allow for different underline styles to appear in the CSS transition. I created a demo showcasing this using the next technique: the clip-path CSS property.

Technique 3: Using clip-path

For this technique, we will be using the clip-path CSS property with a polygon shape. The polygon will have four vertices, with two of them expanding to the right on hover:

The markup is the same as the previous technique. We will use a ::before pseudo-element again, but the CSS is different:

a::before {
  position: absolute;
  content: attr(data-content);
  color: midnightblue;
  text-decoration: underline;
  clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);
  transition: clip-path 275ms ease;
}

Unlike the previous techniques, text-decoration: underline must be declared to the ::before pseudo-element for the color to fill the underline on hover.

Now let’s look into the CSS for the clip-path technique:

clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);

The polygon’s vertices of the clip-path property are set in percentages to define coordinates by the order written:

  • 0 0 = top left
  • 0 0 = top right
  • 100% 0 = bottom right
  • 0 100% = bottom left

The direction of the fill effect can be changed by modifying the coordinates. Now that we have an idea for the coordinates, we can make the polygon expand to the right on hover:

a:hover::before {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

This technique works pretty well, but note that support for the clip-path property varies between browsers. Creating a CSS transition with clip-path is a better alternative than using the width/height technique; however, it does affect the browser paint.

Technique 4: Using transform

The markup for this technique uses a masking method with a <span> element. Since we will be using duplicated content in a separate element, we will use aria-hidden="true" to improve accessibility — that will hide it from screen readers so the content isn’t read twice:

<a href="#"><span data-content="Link Hover" aria-hidden="true"></span>Link Hover</a>

The CSS for the <span> element contains a transition that will be starting from the left:

span {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  transform: translateX(-100%);
  transition: transform 275ms ease;
}

Next, we need to get the <span> to slide the right like this:

To do this, we will use the translateX() CSS function and set it to 0:

a:hover span {
  transform: translateX(0);
}

Then, we will use the ::before pseudo-element for the <span>, again using the data-content attribute we did before. We’ll set the position by translating it 100% along the x-axis.

span::before { 
  display: inline-block;
  content: attr(data-content);
  color: midnightblue;
  transform: translateX(100%);
  transition: transform 275ms ease;
  text-decoration: underline;
}

Much like the <span> element, the position of the ::before pseudo-element will also be set to  translateX(0):

a:hover span::before {
  transform: translateX(0);
}

While this technique is the the most cross-browser compatible of the bunch, it requires more markup and CSS to get there. That said, using the transform CSS property is great for performance as it does not trigger repaints and thus produces smooth, 60fps CSS transitions.

There we have it!

We just looked at four different techniques to achieve the same effect. Although each has its pros and cons, you can see that it’s totally possible to slide in a color change on text. It’s a neat little effect that makes links feel a little more interactive.

The post 4 Ways to Animate the Color of a Text Link on Hover appeared first on CSS-Tricks.

Fixed Headers and Jump Links? The Solution is scroll-margin-top

The problem: you click a jump link like <a href="#header-3">Jump</a> which links to something like <h3 id="header-3">Header</h3>. That's totally fine, until you have a position: fixed; header at the top of the page obscuring the header you're trying to link to!

Fixed headers have a nasty habit of hiding the element you're trying to link to.

There used to be all kinds of wild hacks to get around this problem. In fact, in the design of CSS-Tricks as I write, I was like, "Screw it, I'll just have a big generous padding-top on my in-article headers because I don't mind that look anyway."

But there is actually a really straightforward way of handling this in CSS now.

h3 {
  scroll-margin-top: 5rem; /* whatever is a nice number that gets you past the header */
}

We have an Almanac article on it, which includes browser support, which is essentially everywhere. It's often talked about in conjunction with scroll snapping, but I find this use case even more practical.

Here's a simple demo:

In a related vein, that weird (but cool) "text fragments" link that Chrome shipped takes you to the middle of the page instead, which I think is nice.

The post Fixed Headers and Jump Links? The Solution is scroll-margin-top appeared first on CSS-Tricks.

A Complete Guide to Links and Buttons

There is a lot to know about links and buttons in HTML. There is markup implementation and related attributes, styling best practices, things to avoid, and the even-more-nuanced cousins of the link: buttons and button-like inputs.

Let's take a look at the whole world of links and buttons, and all the considerations at the HTML, CSS, JavaScript, design, and accessibility layers that come with them. There are plenty of pitfalls and bad practices to avoid along the way. By covering it, we’ll have a complete good UX implementation of both elements.

Quick guidelines on when to use each:

  • Are you giving a user a way to go to another page or a different part of the same page? Use a link (<a href="/somewhere">link</a>)
  • Are you making a JavaScript-powered clickable action? Use a button (<button type="button">button</button>)
  • Are you submitting a form? Use a submit input (<input type="submit" value="Submit">)

Links

Links are one of the most basic, yet deeply fundamental and foundational building blocks of the web. Click a link, and you move to another page or are moved to another place within the same page.

Table of Contents

A basic link

<a href="https://css-tricks.com">CSS-Tricks</a>

That's a link to a "fully qualified" or "absolute" URL.

A relative link

You can link "relatively" as well:

<!-- Useful in navigation, but be careful in content that may travel elsewhere (e.g. RSS) -->
<a href="/pages/about.html">About</a>

That can be useful, for example, in development where the domain name is likely to be different than the production site, but you still want to be able to click links. Relative URLs are most useful for things like navigation, but be careful of using them within content — like blog posts — where that content may be read off-site, like in an app or RSS feed.

A jump link

Links can also be "hash links" or "jump links" by starting with a #:

<a href="#section-2">Section Two</a>
<!-- will jump to... -->
<section id="section-2"></section>

Clicking that link will "jump" (scroll) to the first element in the DOM with an ID that matches, like the section element above.

💥 Little trick: Using a hash link (e.g. #0) in development can be useful so you can click the link without being sent back to the top of the page like a click on a # link does. But careful, links that don't link anywhere should never make it to production.

💥 Little trick: Jump-links can sometimes benefit from smooth scrolling to help people understand that the page is moving from one place to another.

It's a fairly common UI/UX thing to see a "Back to top" link on sites, particularly where important navigational controls are at the top but there is quite a bit of content to scroll (or otherwise navigate) through. To create a jump link, link to the ID of an element that is at the top of the page where it makes sense to send focus back to.

<a href="#top-of-page">Back to Top</a>

Jump links are sometimes also used to link to other anchor (<a>) elements that have no href attribute. Those are called "placeholder" links:

<a id="section-2"></a>
<h3>Section 2</h3>

There are accessibility considerations of these, but overall they are acceptable.

Disabled links

A link without an href attribute is the only practical way to disable a link. Why disable a link? Perhaps it's a link that only becomes active after logging in or signing up.

a:not[href] {
  /* style a "disabled" link */
}

When a link has no href, it has no role, no focusability, and no keyboard events. This is intentional. You could think of it like a <span>.

Do you need the link to open in a new window or tab?

You can use the target attribute for that, but it is strongly discouraged.

<a href="https://css-tricks.com" target="_blank" rel="noopener noreferrer">
  CSS-Tricks
</a>

The bit that makes it work is target="_blank", but note the extra rel attribute and values there which make it safer and faster.

Making links open in new tabs is a major UX discussion. We have a whole article about when to use it here. Summarized:

Don't use it:

  • Because you or your client prefer it personally.
  • Because you're trying to beef up your time on site metric.
  • Because you're distinguishing between internal and external links or content types.
  • Because it's your way out of dealing with infinite scroll trickiness.

Do use it:

  • Because a user is doing something on the current page, like actively playing media or has unsaved work.
  • You have some obscure technical reason where you are forced to (even then you're still probably the rule, not the exception).

Need the link to trigger a download?

The download attribute on a link will instruct the browser to download the linked file rather than opening it within the current page/tab. It's a nice UX touch.

<a href="/files/file.pdf" download>Download PDF</a>

The rel attribute

This attribute is for the relationship of the link to the target.

The rel attribute is also commonly used on the <link> element (which is not used for creating hyperlinks, but for things like including CSS and preloading). We're not including rel values for the <link> element here, just anchor links.

Here are some basic examples:

<a href="/page/3" rel="next">Next</a>
<a href="/page/1" rel="prev">Previous</a>

<a href="http://creativecommons.org/licenses/by/2.0/" rel="license">cc by 2.0</a>

<a href="/topics/" rel="directory">All Topics</a>
  • rel="alternate": Alternate version of the document.
  • rel="author": Author of the document.
  • rel="help": A resource for help with the document.
  • rel="license": License and legal information.
  • rel="manifest": Web App Manifest document.
  • rel="next": Next document in the series.
  • rel="prev": Previous document in the series.
  • rel="search": A document meant to perform a search in the current document.

There are also some rel attributes specifically to inform search engines:

  • rel="sponsored": Mark links that are advertisements or paid placements (commonly called paid links) as sponsored.
  • rel="ugc": For not-particularly-trusted user-generated content, like comments and forum posts.
  • rel="nofollow": Tell the search engine to ignore this and not associate this site with where this links to.

And also some rel attributes that are most security-focused:

  • rel="noopener": Prevent a new tab from using the JavaScript window.opener feature, which could potentially access the page containing the link (your site) to perform malicious things, like stealing information or sharing infected code. Using this with target="_blank" is often a good idea.
  • rel="noreferrer": Prevent other sites or tracking services (e.g. Google Analytics) from identifying your page as the source of clicked link.

You can use multiple space-separated values if you need to (e.g. rel="noopener noreferrer")

And finally, some rel attributes come from the microformats standard, like:

  • rel="directory": Indicates that the destination of the hyperlink is a directory listing containing an entry for the current page.
  • rel="tag": Indicates that the destination of that hyperlink is an author-designated "tag" (or keyword/subject) for the current page.
  • rel="payment": Indicates that the destination of that hyperlink provides a way to show or give support for the current page.
  • rel="help": States that the resource linked to is a help file or FAQ for the current document.

ARIA roles

The default role of a link is link, so you do not need to do:

<a role="link" href="/">Link</a>

You'd only need that if you were faking a link, which would be a weird/rare thing to ever need to do, and you'd have to use some JavaScript in addition to this to make it actually follow the link.

<span class="link" tabindex="0" role="link" data-href="/">
  Fake accessible link created using a span
</span>

Just looking above you can see how much extra work faking a link is, and that is before you consider that is breaks right-clicking, doesn't allow opening in a new tab, doesn't work with Windows High Contrast Mode and other reader modes and assistive technology. Pretty bad!

A useful ARIA role to indicate the current page, like:

<a href="/" aria-current="page">Home</a>
<a href="/contact">Contact</a>
<a href="/about">About/a></a>

Should you use the title attribute?

Probably not. Save this for giving an iframe a short, descriptive title.

<a title="I don't need to be here" href="/">
  List of Concerts
</a>

title provides a hover-triggered UI popup showing the text you wrote. You can't style it, and it's not really that accessible.

Hover-triggered is the key phrase here. It's unusable on any touch-only device. If a link needs more contextual information, provide that in actual content around the link, or use descriptive text the link itself (as opposed to something like "Click Here").

Icon-only links

If a link only has an icon inside it, like:

<a href="/">😃</a>

<a href="/">
  <svg> ... </svg>
</a>

That isn't enough contextual information about the link, particularly for accessibility reasons, but potentially for anybody. Links with text are almost always more clear. If you absolutely can't use text, you can use a pattern like:

<a href="/">
  <!-- Hide the icon from assistive technology -->
  <svg aria-hidden="true" focusable="false"> ... </svg>
  <!-- Acts as a label that is hidden from view -->
  <span class="visually-hidden">Useful link text</span>
</a>

visually-hidden is a class used to visually hide the label text with CSS:

.visually-hidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

Unlike aria-label, visually hidden text can be translated and will hold up better in specialized browsing modes.

Links around images

Images can be links if you wrap them in a link. There is no need to use the alt text to say the image is a link, as assistive technology will do that already.

<a href="/buy/puppies/now">
  <img src="puppy.jpg" alt="A happy puppy.">
</a>

Links around bigger chunks of content

You can link a whole area of content, like:

<a href="/article/">
  <div class="card">
    <h2>Card</h2>
    <img src="..." alt="...">
    <p>Content</p>
  </div>
</a>

But it's slightly weird, so consider the UX of it if you ever do it. For example, it can be harder to select the text, and the entire element needs styling to create clear focus and hover states.

Take this example, where the entire element is wrapped in a link, but there are no hover and focus states applied to it.

If you need a link within that card element, well, you can't nest links. You could get a little tricky if you needed ot, like using a pseudo-element on the link which is absolutely positioned to cover the whole area.

Additionally, this approach can make really long and potentially confusing announcements for screen readers. Even though links around chunks of content is technically possible, it's best to avoid doing this if you can.

Here's the default look of a link:

The default User-Agent styling of a link.

It's likely you'll be changing the style of your links, and also likely you'll use CSS to do it. I could make all my links red in CSS by doing:

a {
  color: red;
}

Sometimes selecting and styling all links on a page is a bit heavy-handed, as links in navigation might be treated entirely differently than links within text. You can always scope selectors to target links within particular areas like:

/* Navigation links */
nav a { }

/* Links in an article */
article a { }

/* Links contained in an element with a "text" class */
.text a { }

Or select the link directly to style.

.link {
  /* For styling <a class="link" href="/"> */
}

a[aria-current="page"] {
  /* You'll need to apply this attribute yourself, but it's a great pattern to use for active navigation. */
}

Link states

Links are focusable elements. In other words, they can be selected using the Tab key on a keyboard. Links are perhaps the most common element where you'll very consciously design the different states, including a :focus state.

  • :hover: For styling when a mouse pointer is over the link.
  • :visited: For styling when the link has been followed, as best as the browser can remember. It has limited styling ability due to security.
  • :link: For styling when a link has not been visited.
  • :active: For styling when the link is pressed (e.g. the mouse button is down or the element is being tapped on a touch screen).
  • :focus: Very important! Links should always have a focus style. If you choose to remove the default blue outline that most browsers apply, also use this selector to re-apply a visually obvious focus style.

These are chainable like any pseudo-class, so you could do something like this if it is useful for your design/UX.

/* Style focus and hover states in a single ruleset */
a:focus:hover { }

You can style a link to look button-like

Perhaps some of the confusion between links and buttons is stuff like this:

Very cool "button" style from Katherine Kato.

That certainly looks like a button! Everyone would call that a button. Even a design system would likely call that a button and perhaps have a class like .button { }. But! A thing you can click that says "Learn More" is very much a link, not a button. That's completely fine, it's just yet another reminder to use the semantically and functionally correct element.

Color contrast

Since we often style links with a distinct color, it's important to use a color with sufficient color contrast for accessibility. There is a wide variety of visual impairments (see the tool WhoCanUse for simulating color combinations with different impairments) and high contrast helps nearly all of them.

Perhaps you set a blue color for links:

The blue link is #2196F3.

While that might look OK to you, it's better to use tools for testing to ensure the color has a strong enough ratio according to researched guidelines. Here, I'll look at Chrome DevTools and it will tell me this color is not compliant in that it doesn't have enough contrast with the background color behind it.

Chrome DevTools is telling us this link color does not have enough contrast.

Color contrast is a big consideration with links, not just because they are often colored in a unique color that needs to be checked, but because they have all those different states (hover, focus, active, visited) which also might have different colors. Compound that with the fact that text can be selected and you've got a lot of places to consider contrast. Here's an article about all that.

Styling "types" of links

We can get clever in CSS with attribute selectors and figure out what kind of resource a link is pointing to, assuming the href value has useful stuff in it.

/* Style all links that include .pdf at the end */
a[href$=".pdf"]::after {
  content: " (PDF)";
}

/* Style links that point to Google */
a[href*="google.com"] {
  color: purple;
}

Styling links for print

CSS has an "at-rule" for declaring styles that only take effect on printed media (e.g. printing out a web page). You can include them in any CSS like this:

@media print {
  /* For links in content, visually display the link */ 
  article a::after { 
    content: " (" attr(href) ")";
  }
}

Resetting styles

If you needed to take all the styling off a link (or really any other element for that matter), CSS provides a way to remove all the styles using the all property.

.special-area a {
  all: unset;
  all: revert;
  
  /* Start from scratch */
  color: purple;
}

You can also remove individual styles with keywords. (Again, this isn't really unique to links, but is generically useful):

a {
  /* Grab color from nearest parent that sets it */
  color: inherit;

  /* Wipe out style (turn black) */
  color: initial;

  /* Change back to User Agent style (blue) */
  color: revert;
}

Say you wanted to stop the clicking of a link from doing what it normally does: go to that link or jump around the page. In JavaScript, you can usepreventDefault to prevent jumping around.

const jumpLinks = document.querySelectorAll("a[href^='#']");

jumpLinks.forEach(link => {
 link.addEventListener('click', event => {
    event.preventDefault();
    // Do something else instead, like handle the navigation behavior yourself
  });
});

This kind of thing is at the core of how "Single Page Apps" (SPAs) work. They intercept the clicks so browsers don't take over and handle the navigation.

SPAs see where you are trying to go (within your own site), load the data they need, replace what they need to on the page, and update the URL. It's an awful lot of work to replicate what the browser does for free, but you get the ability to do things like animate between pages.

Another JavaScript concern with links is that, when a link to another page is clicked, the page is left and another page loads. That can be problematic for something like a page that contains a form the user is filling out but hasn't completed. If they click the link and leave the page, they lose their work! Your only opportunity to prevent the user from leaving is by using the beforeunload event.

window.addEventListener("beforeunload", function(event) {
  // Remind user to save their work or whatever.
});

A link that has had its default behavior removed won't announce the new destination. This means a person using assistive technology may not know where they wound up. You'll have to do things like update the page's title and move focus back up to the top of the document.

JavaScript frameworks

In a JavaScript framework, like React, you might sometimes see links created from something like a <Link /> component rather than a native <a> element. The custom component probably creates a native <a> element, but with extra functionality, like enabling the JavaScript router to work, and adding attributes like aria-current="page" as needed, which is a good thing!

Ultimately, a link is a link. A JavaScript framework might offer or encourage some level of abstraction, but you're always free to use regular links.

We covered some accessibility in the sections above (it’s all related!), but here are some more things to think about.

  • You don’t need text like “Link” or “Go to” in the link text itself. Make the text meaningful (“documentation” instead of “click here”).
  • Links already have an ARIA role by default (role="link") so there's no need to explicitly set it.
  • Try not to use the URL itself as the text (<a href="google.com">google.com</a>)
  • Links are generally blue and generally underlined and that's generally good.
  • All images in content should have alt text anyway, but doubly so when the image is wrapped in a link with otherwise no text.

Unique accessible names

Some assistive technology can create lists of interactive elements on the page. Imagine a group of four article cards that all have a "Read More", the list of interactive elements will be like:

  • Read More
  • Read More
  • Read More
  • Read More

Not very useful. You could make use of that .visually-hidden class we covered to make the links more like:

<a href="/article">
  Read More
  <span class="visually-hidden">
    of the article "Dancing with Rabbits".
  <span>
</a>

Now each link is unique and clear. If the design can support it, do it without the visually hidden class to remove the ambiguity for everyone.

Buttons

Buttons are for triggering actions. When do you use the <button> element? A good rule is to use a button when there is “no meaningful href.” Here’s another way to think of that: if clicking it doesn’t do anything without JavaScript, it should be a <button>.

A <button> that is within a <form>, by default, will submit that form. But aside from that, button elements don't have any default behavior, and you'll be wiring up that interactivity with JavaScript.

Table of Contents

HTML implementation

<button>Buy Now</button>

Buttons inside of a <form> do something by default: they submit the form! They can also reset it, like their input counterparts. The type attributes matter:

<form action="/" method="POST">
  <input type="text" name="name" id="name">
  <button>Submit</button>

  <!-- If you want to be more explicit... -->
  <button type="submit">Submit</button>

  <!-- ...or clear the form inputs back to their initial values -->
  <button type="reset">Reset</button>

  <!-- This prevents a `submit` action from firing which may be useful sometimes inside a form -->
  <button type="button">Non-submitting button</button>
</form>

Speaking of forms, buttons have some neat tricks up their sleeve where they can override attributes of the <form> itself.

<form action="/" method="get">

  <!-- override the action -->
  <button formaction="/elsewhere/" type="submit">Submit to elsewhere</button>

  <!-- override encytype -->
  <button formenctype="multipart/form-data" type="submit"></button>

  <!-- override method -->
  <button formmethod="post" type="submit"></button>

  <!-- do not validate fields -->
  <button formnovalidate type="submit"></button>

  <!-- override target e.g. open in new tab -->
  <button formtarget="_blank" type="submit"></button>

</form>

Autofocus

Since buttons are focusable elements, we can automatically focus on them when the page loads using the autofocus attribute:

<div class="modal">

  <h2>Save document?</h2>

  <button>Cancel</button>
  <button autofocus>OK</button>
</div>

Perhaps you'd do that inside of a modal dialog where one of the actions is a default action and it helps the UX (e.g. you can press Enter to dismiss the modal). Autofocusing after a user action is perhaps the only good practice here, moving a user's focus without their permission, as the autofocus attribute is capable of, can be a problem for screen reader and screen magnifier users.

Note thatautofocus may not work if the element is within an <iframe sandbox> for security reasons.

Disabling buttons

To prevent a button from being interactive, there is a disabled attribute you can use:

<button disabled>Pay Now</button>
<p class="error-message">Correct the form above to submit payment.</p>

Note that we've included descriptive text alongside the disabled button. It can be very frustrating to find a disabled button and not know why it's disabled. A better way to do this could be to let someone submit the form, and then explain why it didn't work in the validation feedback messaging.

Regardless, you could style a disabled button this way:

/* Might be good styles for ANY disabled element! */
button[disabled] {
  opacity: 0.5;
  pointer-events: none;
} 

We'll cover other states and styling later in this guide.

Buttons can contain child elements

A submit button and a submit input (<input type="submit">) are identical in functionality, but different in the sense that an input is unable to contain child elements while a button can.

<button>
   <svg aria-hidden="true" focusable="false">
     <path d="..." />
   </svg>
   <span class="callout">Big</span>
   Sale!
</button>

<button type="button">
  <span role="img" aria-label="Fox">
    🦊
  </span>
  Button
</button>

Note the focusable="false" attribute on the SVG element above. In that case, since the icon is decorative, this will help assistive technology only announce the button's label.

Styling and CSS considerations

Buttons are generally styled to look very button-like. They should look pressable. If you're looking for inspiration on fancy button styles, you'd do well looking at the CodePen Topic on Buttons.

1, 2, 3, 4, 5, 6

Cross-browser/platform button styles

How buttons look by default varies by browser and platform.

Just on macOS: Chrome, Safari, and Firefox (they look the same)
Add border: 0; to those same buttons as above, and we have different styles entirely.

While there is some UX truth to leaving the defaults of form elements alone so that they match that browser/platform's style and you get some affordance for free, designers typically don't like default styles, particularly ones that differ across browsers.

Resetting the default button style

Removing all the styles from a button is easier than you think. You'd think, as a form control, appearance: none; would help, but don't count on that. Actually all: revert; is a better bet to wipe the slate clean.

You can see how a variety of properties are involved

And that's not all of them. Here's a consolidated chunk of what Normalize does to buttons.

button {
  font-family: inherit; /* For all browsers */
  font-size: 100%; /* For all browsers */
  line-height: 1.15; /* For all browsers */
  margin: 0; /* Firefox and Safari have margin */
  overflow: visible; /* Edge hides overflow */
  text-transform: none; /* Firefox inherits text-transform */
  -webkit-appearance: button; /* Safari otherwise prevents some styles */
}

button::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

button:-moz-focusring {
  outline: 1px dotted ButtonText;
}

A consistent .button class

In addition to using reset or baseline CSS, you may want to have a class for buttons that gives you a strong foundation for styling and works across both links and buttons.

.button {
  border: 0;
  border-radius: 0.25rem;
  background: #1E88E5;
  color: white;
  font-family: -system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
  padding: 0.25rem 0.5rem;
  margin: 0.25rem;
  cursor: pointer;
}

Check out this Pen to see why all these properties are needed to make sure it works correctly across elements.

Button states

Just as with links, you'll want to style the states of buttons.

button:hover { }
button:focus { }
button:active { }
button:visited { } /* Maybe less so */

You may also want to use ARIA attributes for styling, which is a neat way to encourage using them correctly:

button[aria-pressed="true"] { }
button[aria-pressed="false"] { }

Link-styled buttons

There are always exceptions. For example, a website in which you need a button-triggered action within a sentence:

<p>You may open your <button>user settings</button> to change this.</p>

We've used a button instead of an anchor tag in the above code, as this hypothetical website opens user settings in a modal dialog rather than linking to another page. In this situation, you may want to style the button as if it looks like a link.

This is probably rare enough that you would probably make a class (e.g. .link-looking-button) that incorporates the reset styles from above and otherwise matches what you do for anchor links.

Breakout buttons

Remember earlier when we talked about the possibility of wrapping entire elements in links? If you have a button within another element, but you want that entire outer element to be clickable/tappable as if it's the button, that's a "breakout" button. You can use an absolutely-positioned pseudo-element on the button to expand the clickable area to the whole region. Fancy!

JavaScript considerations

Even without JavaScript, button elements can be triggered by the Space and Enter keys on a keyboard. That's part of what makes them such appealing and useful elements: they are discoverable, focusable, and interactive with assistive technology in a predictable way.

Perhaps any <button> in that situation should be inserted into the DOM by JavaScript. A tall order! Food for thought. 🤔

"Once" handlers

Say a button does something pretty darn important, like submitting a payment. It would be pretty scary if it was programmed such that clicking the button multiple times submitted multiple payment requests. It is situations like this where you would attach a click handler to a button that only runs once. To make that clear to the user, we'll disable the button on click as well.

document.querySelector("button").addEventListener('click', function(event) {
  event.currentTarget.setAttribute("disabled", true);
}, {
    once: true
});

Then you would intentionally un-disable the button and reattach the handler when necessary.

Inline handlers

JavaScript can be executed by activating a button through code on the button itself:

<button onclick="console.log('clicked');">
  Log it.
</button>

<button onmousedown="">
</button>

<button onmouseup="">
</button>

That practice went from being standard practice to being a faux pas (not abstracting JavaScript functionality away from HTML) to, eh, you need it when you need it. One advantage is that if you're injecting this HTML into the DOM, you don't need to bind/re-bind JavaScript event handlers to it because it already has one.

JavaScript frameworks

It's common in any JavaScript framework to make a component for handling buttons, as buttons typically have lots of variations. Those variations can be turned into an API of sorts. For example, in React:

const Button = ({ className, children }) => {
  const [activated, setActivated] = React.useState(false);
  return (
    <button
      className={`button ${className}`}
      aria-pressed={activated ? "true" : "false")
      onClick={() => setActivated(!activated)}
    >
      {children}
    </button>
  );
};

In that example, the <Button /> component ensures the button will have a button class and handles a toggle-like active class.

Accessibility considerations

The biggest accessibility consideration with buttons is actually using buttons. Don't try to replicate a button with a <div> or a <span>, which is, unfortunately, more common than you might think. It's very likely that will cause problems. (Did you deal with focusability? Did you deal with keyboard events? Great. There's still probably more stuff you're forgetting.)

Focus styles

Like all focusable elements, browsers apply a default focus style, which is usually a blue outline.

Focus styles on Chrome/macOS

While it's arguable that you should leave that alone as it's a very clear and obvious style for people that benefit from focus styles, it's also not out of the question to change it.

What you should not do is button:focus { outline: 0; } to remove it. If you ever remove a focus style like that, put it back at the same time.

button:focus {
  outline: 0; /* Removes the default blue ring */

  /* Now, let's create our own focus style */
  border-radius: 3px;
  box-shadow: 0 0 0 2px red;
}
Custom focus style

The fact that a button may become focused when clicked and apply that style at the same time is offputting to some. There is a trick (that has limited, but increasing, browser support) on removing focus styles from clicks and not keyboard events:

:focus:not(:focus-visible) { 
  outline: 0; 
}

ARIA

Buttons already have the role they need (role="button"). But there are some other ARIA attributes that are related to buttons:

  • aria-pressed: Turns a button into a toggle, between aria-pressed="true" and aria-pressed="false". More on button toggles, which can also be done with role="switch" and aria-checked="true".
  • aria-expanded: If the button controls the open/closed state of another element (like a dropdown menu), you apply this attribute to indicate that like aria-expanded="true".
  • aria-label: Overrides the text within the button. This is useful for labeling buttons that otherwise don't have text, but you're still probably better off using a visually-hidden class so it can be translated.
  • aria-labelledby: Points to an element that will act as the label for the button.

For that last one:

<button aria-labelledby="buttonText">
  Time is running out! 
  <span id="buttonText">Add to Cart</span>
</button>

Deque has a deeper dive blog post into button accessibility that includes much about ARIA.

Dialogs

If a button opens a dialog, your job is to move the focus inside and trap it there. When closing the dialog, you need to return focus back to that button so the user is back exactly where they started. This makes the experience of using a modal the same for someone who relies on assistive technology as for someone who doesn't.

Focus management isn't just for dialogs, either. If clicking a button runs a calculation and changes a value on the page, there is no context change there, meaning focus should remain on the button. If the button does something like "move to next page," the focus should be moved to the start of that next page.

Size

Don't make buttons too small. That goes for links and any sort of interactive control. People with any sort of reduced dexterity will benefit.

The classic Apple guideline for the minimum size for a touch target (button) is 44x44pt.

Here's some guidelines from other companies. Fitt's Law tells us smaller targets have greater error rates. Google even takes button sizes into consideration when evaluating the SEO of a site.

In addition to ample size, don't place buttons too close each other, whether they're stacked vertically or together on the same line. Give them some margin because people experiencing motor control issues run the risk of clicking the wrong one.

Activating buttons

Buttons work by being clicked/touched, pressing the Enter key, or pressing the Space key (when focused). Even if you add role="button" to a link or div, you won't get the spacebar functionality, so at the risk of beating a dead horse, use <button> in those cases.

The post A Complete Guide to Links and Buttons appeared first on CSS-Tricks.

This Week in Spring: Talks, Releases, Surveys, and More

Hi, Spring fans! This week I am in beautiful Tokyo, Japan, where I just spoke at the always lovely annual Spring Fest event. I loved the show, and I hope that the audience got something out of my performance.

Last week was tough. Possibly the toughest week of my life. I didn’t publish an episode of A Bootiful Podcast, as such. You won’t see that episode reflected on the blog because it was my heartbroken dedication to my father, who passed away last week at the age of 81. No interview in that brief, less-than-20 minutes episode.

The Best of Java Collections [Tutorials]

Who doesn't love a good collection?

When it comes to building Java applications, the Java Collections Framework (JCF) has become ubiquitous among developers. Since the release of JDK 2, Java objects and data structures have changed development for the better, boosting performance and reducing programming efforts.

Oracle defines collections and the JCF as: