3 useful CSS properties to customize your web interactions
A CSS complaint I often see online — one that I largely agree with — is there are too many properties to learn. After learning the basics, it feels like you are then asked to 'memorize the rest of the dictionary'.
Like building a vocabulary, it's easier to add to your CSS knowledge slowly over time than reading the entire spec over a weekend. Today, I want to share 3 of my favorite "new to me" CSS properties from the last year.
user-select
There are few things more frustrating than site owners disabled text selection with user-select: none;
. This is usually done with the intent of copy-prevention. Doing so not only violates web conventions but it doesn't even work since one can always access the HTML directly.
user-select: none
is not what I want to focus on. I want to mention the lesser-known value: user-select: all;
. The all
value causes any selection inside the element to select all element text, even with a single click.
This means you can use HTML elements as semantic 'highlight sections' to group related content together. Some interesting use-cases:
-
<address>
it makes sense to wrap an entire name/address /telephone in a single copy section. So the user can copy an entire address in a rental listing into Google Maps to lookup commute distance. <code>
you can wrap sections of code in its own<div>
to make copy/pasting easier.
See the Pen User-select by Shimin Zhang (@shimin-zhang) on CodePen.
Like all techniques, user-select: all
involves some tradeoff, it can make common copy/highlights tasks easier but comes at a cost of breaking existing user expectations.
pointer-events
Pointer event is yet another CSS property that affects interactions, you can use it to change how an element interacts with mouse events.
The most common use case for pointer events is adding pointer-events:none
to an element so that it can no longer be clicked on — see this example from David Walsh. This way, you can use CSS selectors to determine whether some elements should be transparent to the hit-testing algorithm, a better alternative to adding checks inside the click event handler for its current target and manually calling preventDefault()
.
Aside from using it to disable buttons and links, pointer-events:none
is helpful when you have some overlapping components and want to pass the click event through one layer to another one underneath. See this example where inline SVG icons overlap with a <select>
element, yet clicking on the icons will pass the event through to the select.
See the Pen Pointer-Events by Shimin Zhang (@shimin-zhang) on CodePen.
Resize
The last CSS property I want to point out is resize
, the resize
prop allows users to modify an HTML element's size — hence the name.
You are probably already familiar with the resizing behavior in the context of the <textarea>
element. Resize behavior works well with textarea because we do not know in advance how much content a user will supply. You can disable this default behavior via resize: none
.
But resize
is not limited to just <textarea>
elements. You can make all content without overflow: visible
resizable. Either in the horizontal
, vertical
or both
directions.
Here's a demo of a resizable reading window with a resizable range input that allows you to change the reading font size.
See the Pen resize by Shimin Zhang (@shimin-zhang) on CodePen.
Depending on the input range, a resizable range input could be a more intuitive approach than using the keyboard or clicking with the mouse for a pixel-perfect value.
Conclusion
While we generally consider HTML to be about a document's semantics, CSS for its look and feel, and JS for user interaction, this categorization is not absolute.
Just as the disabled
HTML attributes can affect an element's interactivity, there are a number of CSS properties that handle more than styling. Following the Rule of Least Power, we should look for HTML and CSS solutions before reaching for a pure JS one.
If you are not familiar with the resize
, user-select
, and pointer-events
properties — or it's been a while since you last looked them up — I encourage you to take a look at the examples and maybe look up the docs to refresh your memory.