Recently I came across a CodePen demo by a developer/engineer named Jane that was Tweeted out by Šime Vidas. The demo has a neat collection of HTML and CSS tricks rolled into one that I thought was worth examining in detail.
The page displays a secret message based on specific text input. Ok, that’s no big deal, right? Well this is done using pure HTML and CSS – no JavaScript. I’ve seen stuff like this before, but I thought it would be cool to break down exactly how this works. There are a few notable things happening in the code so I’ll break down each of the parts. Here’s the demo:
See the Pen
Add secret website button codes with vanilla CSS (NO JS!) by Jane 💜 (@propjockey)
on CodePen.
Just make sure, as the instruction says, that your cursor is focused inside the CodePen preview window.
Using HTML’s accesskey
As the revealed secret message points out, the demo is using HTML’s accesskey
attribute. That’s a bit of a blast from the past for some of us. It’s an old feature that:
provides a hint for generating a keyboard shortcut for the current element.
This means the user can trigger focus on the targeted element using a browser- or platform-specific key combination along with the specified accesskey
value (which can be any “printable” character generated by the keyboard).
You can set up an accesskey
value like this:
<input accesskey="c">
MDN’s article on accesskey
has a handy chart showing how the accesskey can be triggered by the user on different browsers and platforms. The most likely combination is either ALT-KEY (Windows) or CTRL-ALT-KEY (Mac) – though there are a lot of variations depending on the browser.
In Jane’s demo, the input is visually hidden but still accessible. I’ll get to more on accesskey
in a moment but let’s also look at the other interesting things in the demo.
Using the pattern
Attribute
The other thing that makes this trick work is the use of the pattern
attribute on the hidden text field. Strangely, MDN’s article doesn’t display the browser compatibility for pattern
, but the attribute seems to be safe to use. If I recall correctly, this feature was added a little later than other HTML5 forms features.
This attribute accepts a regular expression that should be matched for the form field to validate. It can be used on text
, tel
, email
, url
, password
, and search
inputs.
In this instance, the demo isn’t using any special regex characters to do anything fancy – it’s just straight text that’s matched.
<input accesskey="c" pattern="wow!">
But there’s no form submission going on here, so how is this form field being “validated”?
The :valid
and :placeholder-shown
Pseudo-classes
In order to check if the form field is valid, the demo makes use of the :valid
CSS pseudo-class. So you can do something like the following to apply different styles to a form field that’s valid but hasn’t been submitted yet:
:valid {
border: solid 1px green;
}
This will instantly place a green border on any valid form field, no need for form submission. There’s also a pseudo-class of :invalid
which does the opposite. Both have good browser support, so don’t be afraid to use these.
The demo also uses the :placeholder-shown
pseudo-class. This pseudo-class targets elements that are using the HTML placeholder
attribute and whose placeholder
value is visible (i.e. the user hasn’t inserted text to remove the placeholder value).
:placeholder-shown {
background: white;
}
This feature isn’t important to the overall technique, but it’s part of the big selector that I’ll discuss next.
The Big Fancy CSS Selector
Once we understand those two pseudo-classes, then we can begin to grasp the big selector used in the demo:
.secret-code:not(:placeholder-shown):valid ~ * {
--secret_code: ;
}
In addition to the :valid
and :placeholder-shown
pseudo-classes, the selector is using the more common :not()
pseudo-class along with a sibling selector and a universal selector. That’s quite a bit to digest in a single CSS selector, but here’s what it means in plain English:
- Target all sibling elements
- Of every element with a class name of
.secret-code
- That has no placeholder text showing
- That’s valid
And once we grasp that selector, then we can move on to the main CSS trick used to toggle the secret message on and off.
The --var()
Space-toggle Hack
The demo is using a trick referred to as the space-toggle hack (or var-toggle hack), which Lea Verou nicely explained a year ago and apparently was first used/discovered by Ana Tudor. This trick uses CSS custom properties (i.e. CSS Variables). In fact, Jane has used it in multiple projects including CSS Mine Sweeper and a library called Augmented UI.
This technique is a way to easily toggle a set of CSS property/value pairs on a single element using a single property value.
Take note of the inline styles present on the div
element in the demo:
<div style="--wow: var(--secret_code) green; color: var(--wow, black);">
The odd thing here, and the thing that makes the space-toggle hack work, is the value for the --wow
custom property. Before the selector criteria is met, the value of this custom property is invalid. This is because the --secret_code
variable has no value set (yet). The value of green
that appears after the invalid custom property will take effect once the space character is put in place (hence the name “space-toggle hack”).
This essentially means --wow: var(--secret_code) green;
will compute to --wow: green;
(because the space is just extra white space, which is fine inside a CSS value).
To make it more clear, in plain English the inline style reads like this:
- Define the
--wow
variable with a non-existent custom property followed by a space and the color green - Set the
color
property to whatever the--wow
variable is set to (currently invalid), with a fallback ofblack
- Since
--wow
is currently invalid, use its fallback
This is why the color of the text starts out black when you first load the page.
The key to the toggle, then, is to add a space character as a value for --secret_code
. This makes the initial definition of --wow
valid, so the fallback color of black isn’t used. Once the space character is inserted, the logic is like this:
- Define the
--wow
variable with a space character, followed by another space and the color green - Set the
color
property to whatever the--wow
variable is set to (currently a valid space), with a fallback ofblack
- Since
--wow
is currently valid, and doesn’t break the value ofgreen
, the color is computed togreen
The same logic applies to the hidden span
element that shows the secret message:
<span style="--wow: var(--secret_code) block; display: var(--wow, none);">
Again, the value of “block” won’t take effect until the selector criteria is met, thus making var(--secret_code)
valid (and, by extension, --wow
is valid).
One of the things that first tripped me up about the space-toggle hack is the value that follows the invalid variable. In this case it was green
. To me this looked like a fallback value, so the logic didn’t make sense at first glance. But this isn’t a fallback value; it’s a value that gets toggled “on” when the variable next to it gets validated by the space character passed in from the selector’s variable definition.
And one final thing about the space-toggle hack: It’s really not recommended in a lot of cases and will cause problems with some CSS minifiers. A minifier is usually going to delete unwanted space characters like the one set as the value in this hack. I tested it on a few online minifiers and it does indeed cause problems for some, but not all. So be aware of that if you choose to use this technique.
Final Warning About Using accesskey
As mentioned, this trick uses the accesskey
attribute, which seems like a useful feature to take advantage of. As the original Tweet by Šime mentions, WebAIM provides a warning when discussing this subject:
Despite good intentions and because of varied and insufficient browser implementations,
accesskey
very often does not provide a viable solution for keyboard shortcuts on the web.
They go on to offer a whole slew of reasons why using accesskey
is problematic and conclude with:
Due to numerous problems with implementation,
accesskey
is typically best avoided. If used, they must be implemented carefully. The bottom line: some users will benefit and some will not, and some may even be disadvantaged.
While the accesskey
part of this trick is the primary reason it works, I hope the rest of it (which is more likely to be used) was somewhat educational to those of you who weren’t as familiar with it all.
This can be useful for customizing UI or providing feedback when users enter specific text. Thanks for sharing this post with us.
This can be very helpful when detecting spam comments of custom websites as we’ll be able to detect the spammy comments & messages submitted through forms.
This is very useful article. It can be helpful to detect the spam comments.