What CSS appearance Actually Does
appearance: none can remove the familiar arrow from a select or the native presentation of a checkbox. The element keeps its HTML functionality, but the visual cues it relied on may now be missing.
CSS appearance is worth treating as a deliberate styling choice. A reset that removes the control’s identity creates work that a border or colour adjustment might have avoided.
View code
<label for="native">Native presentation</label><select id="native"><option>Latvia</option><option>Estonia</option><option>Lithuania</option></select>
<label for="bare">appearance: none</label><select id="bare" class="bare"><option>Latvia</option><option>Estonia</option><option>Lithuania</option></select>
<label for="styled">Restyled with an arrow</label><span class="select-wrap"><select id="styled"><option>Latvia</option><option>Estonia</option><option>Lithuania</option></select></span>
<p class="note">All three are real selects. Try opening each one and using the keyboard; only their presentation changes.</p>button, select { padding: .35rem .6rem; border: 1px solid var(--clg); background: var(--cw); color: var(--cb); }
input[type="range"] { width: min(100%, 18rem); vertical-align: middle; }
h2, h3 { font-size: 1rem; }
.note { color: var(--clg); }
label { display: block; margin-block: .75rem .3rem; }
select { display: block; width: min(100%, 18rem); padding: .5rem; }
.bare, .select-wrap select { appearance: none; }
.select-wrap { position: relative; display: block; width: min(100%, 18rem); }
.select-wrap select { width: 100%; padding-inline-end: 2.5rem; }
.select-wrap::after { content: ''; position: absolute; inset-inline-end: 1rem; top: 50%; width: .4rem; height: .4rem; border-inline-end: 2px solid currentColor; border-block-end: 2px solid currentColor; transform: translateY(-70%) rotate(45deg); pointer-events: none; }See what appearance removes from a select
Begin with a labelled native select:
<label for="country">Country</label>
<select id="country" name="country">
<option>Latvia</option>
<option>Estonia</option>
<option>Lithuania</option>
</select>
select {
appearance: none;
}
The appearance documentation explains that none suppresses native presentation while retaining functionality. Removing the select’s normal arrow can make it look like a text field, even though it still opens a choice list.
The styling change does not replace the select with a custom widget. Its native behaviour remains, which is a different decision from rebuilding the interaction from generic elements.
Put back the visual affordance you removed
A wrapper can supply a decorative arrow while the select remains the interactive element:
<label for="region">Region</label>
<span class="select-wrap">
<select id="region" name="region">
<option>Europe</option>
<option>Asia</option>
</select>
</span>
.select-wrap {
position: relative;
display: inline-block;
}
.select-wrap select {
appearance: none;
font: inherit;
color: inherit;
background: transparent;
border: 1px solid currentColor;
border-radius: 0.5rem;
padding: 0.75rem 2.5rem 0.75rem 1rem;
}
.select-wrap::after {
content: "";
position: absolute;
inset-inline-end: 1rem;
top: 50%;
width: 0.4rem;
height: 0.4rem;
border-inline-end: 2px solid currentColor;
border-block-end: 2px solid currentColor;
transform: translateY(-70%) rotate(45deg);
pointer-events: none;
}
The extra inline-end padding leaves room for the arrow. The wrapper’s pseudo-element is decoration, and pointer events still reach the select beneath it.
This is a small styling example for ordinary horizontal text, not a complete select design for every writing mode. Check the arrow and padding with longer option labels before reusing the wrapper.
Keep the native element’s contract
A styled select still needs a label, a useful name for submission, and options that make sense. The select element reference describes those HTML responsibilities.
Removing appearance does not remove that contract. It also does not guarantee that the remaining presentation is understandable: a keyboard-operable control can still be difficult to recognise.
That distinction matters for checkboxes and radio buttons in particular. With native appearance removed, a checked indicator can disappear unless the replacement styles provide one. A generic input { appearance: none; } reset reaches much further than a single select arrow.
Try a smaller change for checkboxes
When the required change is just the accent colour, a native checkbox can keep its presentation:
input[type="checkbox"],
input[type="radio"] {
accent-color: #4d5cff;
}
Accent-color supplies that narrower control. It does not require recreating selected and unselected visuals from scratch.
A custom shape may justify taking over more styling. A purple checkmark by itself is a weaker reason to discard the native one.
Buttons and search fields need separate decisions
A button can often receive ordinary font, border, and padding styles without an appearance reset:
button {
font: inherit;
border: 1px solid currentColor;
border-radius: 0.5rem;
padding: 0.75rem 1rem;
}
Search inputs can include browser-specific decorations such as clear controls. Check the search input’s native presentation rather than assuming every input shares the same details.
Target the particular control whose presentation needs changing. A rule intended for a search field should not silently become the styling policy for an entire form.
Inspect focus and contrast after restyling
Native appearance varies by browser and operating system. Removing it can expose different remaining defaults, so a result on one platform is not proof of a consistent result elsewhere.
Keep keyboard focus visible and check disabled and selected states with actual labels. High-contrast settings also belong in the review when the control relies on a decorative border or arrow.
I would keep native appearance when the ordinary CSS properties achieve the design. When opting out, identify the visual cue being replaced and make its replacement part of the same change. A missing arrow is easy to overlook once the select has a neat new border.