You may have seen ghost buttons? They are characterized by transparent backgrounds and the background is filled with solid color when the mouse hovers. Smashing Magazine has an article on this topic. This article will build a ghost button, but this part is relatively simple. Interestingly and tricky, we're going to have the fill animation of the ghost button start at the mouse hover.
Here is a basic ghost button example:
In most cases, the background color transitions to the solid color. Some designs will fill the buttons from left to right, top to bottom, etc. to increase the visual effect. For example, fill from left to right:
Here is a small user experience problem. If the mouse hovers over the edge of the filled area, it will feel something is wrong. Consider this example, the button fills from the left, while you hover from the right.
It is best to have the button fill from the initial hover point.
So, how do we give button direction perception ? Your initial intuition might be to use JavaScript, but we can do it with CSS and some extra tags.
For those who want to get a quick look at the results, here are some direction-aware ghost buttons implemented in pure CSS!
Let's build it step by step. All code can be found in this CodePen collection.
Create a basic
Let's start with the basics of creating the ghost button. The marking is simple.
<button>Boo!</button>
Our CSS implementation will utilize CSS custom properties. This makes maintenance easier and also facilitates customization through inline properties.
button { --borderWidth: 5; --boxShadowDepth: 8; --buttonColor: #f00; --fontSize: 3; --horizontalPadding: 16; --verticalPadding: 8; background: transparent; border: calc(var(--borderWidth) * 1px) solid var(--buttonColor); box-shadow: calc(var(--boxShadowDepth) * 1px) calc(var(--boxShadowDepth) * 1px) 0 #888; color: var(--buttonColor); cursor: pointer; font-size: calc(var(--fontSize) * 1rem); font-weight: bold; outline: transparent; padding: calc(var(--verticalPadding) * 1px) calc(var(--horizontalPadding) * 1px); transition: box-shadow 0.15s ease; } button:hover { box-shadow: calc(var(--boxShadowDepth) / 2 * 1px) calc(var(--boxShadowDepth) / 2 * 1px) 0 #888; } button:active { box-shadow: 0 0 0 #888; }
Put it together and we get:
very good! We have a button and hover effect, but there is no fill effect yet. Next let's add the fill effect.
Add fill
To do this, we create some elements to display the fill state of the ghost button. The trick is to use clip-path
to crop these elements and hide them. We can display them on hover by converting clip-path
.
They must be aligned with the parent button. Our CSS variables will be of great help here.
At first, we might consider using pseudo-elements. However, for each direction, the number of pseudo-elements is not enough. They also affect accessibility…more on that later.
Let's start by adding a basic left-to-right padding. First, let's add one<span></span>
element. Should<span></span>
The element needs to have the same text content as the button.
<button> <span>Boo!</span> Boo! </button>
Now we need to<span></span>
Elements are aligned with buttons. Our CSS variables will do most of the work.
button span { background: var(--buttonColor); border: calc(var(--borderWidth) * 1px) solid var(--buttonColor); bottom: calc(var(--borderWidth) * -1px); color: var(--bg, #fafafa); left: calc(var(--borderWidth) * -1px); padding: calc(var(--verticalPadding) * 1px) calc(var(--horizontalPadding) * 1px); position: absolute; right: calc(var(--borderWidth) * -1px); top: calc(var(--borderWidth) * -1px); }
Finally, we will<span></span>
The element is cropped outside the view and adds a rule to display it on hover by updating the crop. Defining a transition will add icing on the cake.
button span { --clip: inset(0 100% 0 0); -webkit-clip-path: var(--clip); clip-path: var(--clip); transition: clip-path 0.25s ease, -webkit-clip-path 0.25s ease; /* ...Remaining div styles */ } button:hover span { --clip: inset(0 0 0 0); }
Add directional awareness
So, how do we add directional awareness? We need four elements. Each element will be responsible for detecting the hover entry point. Using clip-path
, we can divide the button area into four parts.
Let's add four to the button<span></span>
elements and position them to fill the buttons.
<button> <span></span> <span></span> <span></span> <span></span> Boo! </button>
button span { background: var(--bg); bottom: calc(var(--borderWidth) * -1px); -webkit-clip-path: var(--clip); clip-path: var(--clip); left: calc(var(--borderWidth) * -1px); opacity: 0.5; position: absolute; right: calc(var(--borderWidth) * -1px); top: calc(var(--borderWidth) * -1px); z-index: 1; }
We can locate each element and assign crops and colors using CSS variables.
button span:nth-of-type(1) { --bg: #00f; --clip: polygon(0 0, 100% 0, 50% 50%, 50% 50%); } button span:nth-of-type(2) { --bg: #f00; --clip: polygon(100% 0, 100% 100%, 50% 50%); } button span:nth-of-type(3) { --bg: #008000; --clip: polygon(0 100%, 100% 100%, 50% 50%); } button span:nth-of-type(4) { --bg: #800080; --clip: polygon(0 0, 0 100%, 50% 50%); }
Very cool. To test this, let's change the opacity while hovering.
button span:nth-of-type(1):hover, button span:nth-of-type(2):hover, button span:nth-of-type(3):hover, button span:nth-of-type(4):hover { opacity: 1; }
Oh, there is a question here. If we go in and hover over one section and then hover over another, the filling direction will change. This doesn't seem right. To solve this problem, we can set z-index
and clip-path
on hover so that a part of the space is filled.
button span:nth-of-type(1):hover, button span:nth-of-type(2):hover, button span:nth-of-type(3):hover, button span:nth-of-type(4):hover { --clip: polygon(0 0, 100% 0, 100% 100%, 0 100%); opacity: 1; z-index: 2; }
Combine together
We know how to create fill animations, and we know how to detect directions. How do we combine the two? Use a combo at the same level!
Doing this means that when we hover a segment, we can display a specific fill element.
First, let's update the tag.
<button> <span></span> <span></span> <span></span> <span></span> <b>Boo!</b> <b>Boo!</b> <b>Boo!</b> <b>Boo!</b> Boo! </button>
Now, we can update the CSS. Referring to our left-to-right padding, we can reuse styles. We just need to set a specific clip-path
for each element. I handled it in the same order as some attribute values. The first child element is the top, the second is the right, and so on.
button b:nth-of-type(1) { --clip: inset(0 0 100% 0); } button b:nth-of-type(2) { --clip: inset(0 0 0 100%); } button b:nth-of-type(3) { --clip: inset(100% 0 0 0); } button b:nth-of-type(4) { --clip: inset(0 100% 0 0); }
The last step is to update clip-path
of the relevant element when hovering the pairing segment.
button span:nth-of-type(1):hover ~ b:nth-of-type(1), button span:nth-of-type(2):hover ~ b:nth-of-type(2), button span:nth-of-type(3):hover ~ b:nth-of-type(3), button span:nth-of-type(4):hover ~ b:nth-of-type(4) { --clip: inset(0 0 0 0); }
alright! We get a pure CSS ghost button with directional awareness.
Accessibility
In the current state, the button is inaccessible.
These extra elements don't help much, as the screen reader repeats the content four times. We need to hide these elements from the screen reader.
<button> <span></span> <span></span> <span></span> <span></span> <b aria-hidden="true">Boo!</b> <b aria-hidden="true">Boo!</b> <b aria-hidden="true">Boo!</b> <b aria-hidden="true">Boo!</b> Boo! </button>
No more duplicate content.
that's all!
With just some extra marking and some CSS tricks, we can create ghost buttons with directional awareness. Using a preprocessor or combining a component in your application, you don't need to write out all the HTML.
This is a demonstration of using inline CSS variables to control button color.
This revised output maintains the original image and uses more concise and varied phrasing while preserving the core meaning of the original text. It also addresses the accessibility issue mentioned in the original article.
The above is the detailed content of Ghost Buttons with Directional Awareness in CSS. For more information, please follow other related articles on the PHP Chinese website!

For a while, iTunes was the big dog in podcasting, so if you linked "Subscribe to Podcast" to like:

We lost Opera when they went Chrome in 2013. Same deal with Edge when it also went Chrome earlier this year. Mike Taylor called these changes a "Decreasingly

From trashy clickbait sites to the most august of publications, share buttons have long been ubiquitous across the web. And yet it is arguable that these

In this week's roundup, Apple gets into web components, how Instagram is insta-loading scripts, and some food for thought for self-hosting critical resources.

When I was looking through the documentation of git commands, I noticed that many of them had an option for . I initially thought that this was just a

Sounds kind of like a hard problem doesn't it? We often don't have product shots in thousands of colors, such that we can flip out the with . Nor do we

I like when websites have a dark mode option. Dark mode makes web pages easier for me to read and helps my eyes feel more relaxed. Many websites, including

This is me looking at the HTML element for the first time. I've been aware of it for a while, but haven't taken it for a spin yet. It has some pretty cool and


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 English version
Recommended: Win version, supports code prompts!

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

SublimeText3 Chinese version
Chinese version, very easy to use

SublimeText3 Mac version
God-level code editing software (SublimeText3)