In short
CSS user interface properties control how people interact with a page: resize, cursor, caret-color, user-select, pointer-events, scrollbar colors and accent-color. What are CSS user interface properties? Most CSS changes how a page looks.
CSS user interface properties control how people interact with a page: resize, cursor, caret-color, user-select, pointer-events, scrollbar colors and accent-color.
What are CSS user interface properties?
Most CSS changes how a page looks. A small group of properties changes how it feels to use: what the mouse pointer looks like, whether a box can be resized, whether text can be selected, and the color of the blinking text cursor. These are the user interface properties. Small details like these are like the handles on doors: people only notice them when they are wrong.
You have already seen cursor: pointer on buttons and accent-color on checkboxes in the Styling Forms and Buttons lesson. Here we look at the full set.
The resize property: let users resize a textarea or box
The resize property decides whether the user can drag the corner of an element to change its size. By default, a <textarea> can be resized in both directions.
<label for="msg">Your message</label>
<textarea id="msg" class="message" rows="5"></textarea>
<div class="note-box">Drag my bottom-right corner to make me wider or taller.</div>
.message {
width: 100%;
min-height: 120px;
max-height: 400px;
resize: vertical;
}
.note-box {
width: 250px;
height: 120px;
padding: 1rem;
border: 1px dashed #6b7280;
overflow: auto;
resize: both;
}
The textarea can now only be made taller or shorter, never wider, so it can't break your layout. min-height and max-height set limits on how far it can go. The dashed <div> gets a small drag handle in its corner and can be resized both ways.
| Value | Meaning |
|---|---|
none | Can't be resized |
both | Width and height |
horizontal | Width only |
vertical | Height only |
block / inline | Along the block or inline direction (follows the writing mode) |
Common mistake: Adding
resize: bothto a<div>and nothing happens.resizeonly works whenoverflowis something other thanvisible, for exampleautoorhidden. Textareas already have this, but divs needoverflow: auto.
The cursor property: change the mouse pointer
The cursor property sets the mouse pointer shape when it is over an element. The right cursor tells the user what will happen before they click.
| Value | Looks like | Use it for |
|---|---|---|
auto | Browser decides | The default |
default | Normal arrow | Things that are not clickable |
pointer | Pointing hand | Buttons and clickable cards |
text | I-beam | Selectable text, inputs |
move | Four arrows | Something you can drag anywhere |
grab / grabbing | Open / closed hand | Draggable items, before and during dragging |
not-allowed | Circle with a line | Disabled buttons |
wait | Spinner or hourglass | The whole page is busy |
progress | Arrow with a spinner | Busy, but you can still click |
help | Arrow with a question mark | Extra info is available |
crosshair | Thin cross | Precise picking, drawing tools |
zoom-in / zoom-out | Magnifying glass | Images that zoom |
col-resize / row-resize | Arrows with a bar | Dragging column or row dividers |
none | Hidden | Games, custom cursors (use rarely) |
.product-card { cursor: pointer; }
.gallery img { cursor: zoom-in; }
.draggable { cursor: grab; }
.draggable:active { cursor: grabbing; }
abbr[title] { cursor: help; }
.paint-area {
cursor: url("brush.png") 4 28, crosshair;
}
Hover each element to see a different pointer: a hand on the card, a magnifier on gallery images, an open hand on the draggable item that closes while you hold the mouse button. For .paint-area, the browser uses your own brush.png image. The two numbers 4 28 are the "hot spot", the exact pixel that does the clicking. After the comma, crosshair is a fallback if the image fails to load; a keyword fallback is always required after a url().
Tip: Don't put
cursor: pointeron everything. Use it for things that act when clicked. Normal text should keep the I-beam so people know they can select it.
caret-color and user-select
The caret is the blinking line that shows where you are typing. caret-color changes its color, which is a nice touch for a brand color or a dark theme.
.search-input {
caret-color: #e11d48;
}
.code-editor {
background: #0f172a;
color: #e2e8f0;
caret-color: #facc15;
}
Click into the search field and the blinking line is pink-red instead of black. In the dark editor, a yellow caret is easy to spot on the dark background.
user-select controls whether people can select (highlight) text.
<button class="btn" type="button">Add to cart</button>
<p>Your coupon code: <code class="coupon">SPRING-25</code></p>
.btn {
user-select: none;
}
.coupon {
-webkit-user-select: all; /* older Safari */
user-select: all;
}
Double-click the button text quickly: nothing gets highlighted, so fast clicks don't select the label by accident. Click once on the coupon code and the whole code is selected at once, ready to copy, instead of just one word.
| Value | Meaning |
|---|---|
auto | Normal behavior (default) |
none | Text can't be selected |
text | Text can be selected |
all | One click selects the whole element |
Note: Never use
user-select: noneon articles or normal content to "protect" your text. It doesn't stop copying (anyone can view the source), and it annoys people who select text to translate it, look up a word or read along.
pointer-events and custom scrollbars
pointer-events: none makes the mouse "pass through" an element, as if it were made of glass. Clicks, hovers and the cursor go to whatever is behind it.
.hero {
position: relative;
}
.hero::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(to top, rgb(0 0 0 / 0.6), transparent);
pointer-events: none;
}
The dark gradient overlay sits on top of the hero section, but you can still click the links and buttons under it. Without pointer-events: none, the overlay would catch every click. This is the same trick we used for tooltips. Remember that pointer-events: none only affects the mouse and touch: keyboard users can still Tab to a link, so it is not a way to disable something.
You can also style scrollbars with two standard properties. scrollbar-color takes two colors: the thumb (the part you drag) and the track (the line it moves along). scrollbar-width takes auto, thin or none.
.chat-messages {
height: 300px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: #94a3b8 #f1f5f9;
}
The chat box gets a thin grey scrollbar on a very light track. These properties work in Chrome, Edge and Firefox, and newer Safari versions support scrollbar-width; browsers without support simply show the normal scrollbar, so it is safe to use. Use scrollbar-width: none very carefully: hiding the scrollbar can make people miss that there is more content.
Finally, accent-color colors checkboxes, radio buttons, range sliders and progress bars with one line, for example accent-color: #16a34a;. You learned it in the Styling Forms and Buttons lesson. See the full list of UI properties on MDN: CSS basic user interface.
Practice exercise
Build a small "Notes" app layout: a <textarea> that can only grow taller (between 150px and 500px), a pink caret, a "Copy note ID" line where one click selects the whole ID, a draggable-looking note card with grab and grabbing cursors, and a notes list with a thin, colored scrollbar.
Hint: you need resize: vertical, caret-color, user-select: all, cursor: grab plus :active { cursor: grabbing; }, and scrollbar-width with scrollbar-color on a box with a fixed height and overflow-y: auto.
Key takeaways
resizelets users resize textareas and boxes, but only whenoverflowis notvisible.cursortells people what will happen:pointerfor clickable,not-allowedfor disabled,grabfor draggable.caret-colorcolors the typing cursor;user-selectcontrols text selection, so usenoneonly on UI controls.pointer-events: nonelets clicks pass through overlays, but it does not block keyboard users.scrollbar-color,scrollbar-widthandaccent-colorstyle built-in browser parts with a single line.