Two small properties for a lot of fine control over forms
accent-color and caret-color sound similar but control entirely different things: one colors native controls like checkboxes and radios, the other colors only the blinking caret inside a text field. Used deliberately, both let you build a custom form theme without redrawing every control with appearance: none.
Table of Contents
- 1. accent-color and caret-color: two properties with different jobs
- 2. accent-color in detail: which elements are affected
- 3. caret-color in detail: the color of the text caret
- 4. Combining both in a custom form theme
- 5. Inheritance and scoping: where each property takes effect
- 6. Contrast, focus indicators and forced-colors mode
- 7. Browser support and fallback strategies
- 8. Practical example: a checkout form with a coherent color scheme
- 9. Common mix-ups and how to avoid them
- 10. Summary
- 11. FAQ
1. accent-color and caret-color: two properties with different jobs
Both properties carry the word color in their name and often show up in the same form stylesheet, which is exactly why they get confused. accent-color sets the accent color of a native control, meaning the filled state of a checkbox, the dot inside a radio button, the thumb of a range input, or the fill bar of a progress element. caret-color instead affects only the insertion mark, the blinking line showing where the next typed character will land.
The reason for two separate properties is that both areas of a form are entirely independent: a text field has no accent state, and a checkbox has no caret. Browser vendors deliberately avoided a single, overloaded property so developers can set colors precisely where they are visually needed, without risking side effects on unrelated form elements.
2. accent-color in detail: which elements are affected
accent-color applies to a limited but practically relevant list of native form elements: input[type=checkbox], input[type=radio], input[type=range] and progress. The browser automatically derives matching states for hover, focus and the unselected border, without any need to define extra pseudo-classes yourself. That saves substantial effort compared to a fully custom checkbox design built with appearance: none.
Because accent-color builds on top of the operating system's rendering of that control, the result looks slightly different across browsers and platforms, yet stays natively accessible: keyboard navigation, screen reader announcements and high-contrast modes keep working as expected, because no div ever replaces the real form element.
/* accent-color colors checkbox, radio, range and progress consistently */
:root {
--brand-accent: #7c3aed;
}
input[type="checkbox"],
input[type="radio"],
input[type="range"],
progress {
accent-color: var(--brand-accent);
}
/* Optional: a different accent color per context */
.form-danger input[type="checkbox"] {
accent-color: #dc2626;
}
3. caret-color in detail: the color of the text caret
caret-color applies to every element with editable text: input, textarea, and elements with contenteditable. By default the caret inherits the element's text color (color), which is usually unobtrusive but can also become invisible on fields with a colored background. A dedicated caret-color lets you make the caret more visible or match it to a brand color, independently of the actual text.
A common use case is a dark search field with light text on a dark background: without an explicit caret-color, the caret automatically inherits the light text color and stays well visible, but as soon as a distinct accent color is desired, caret-color has to be set separately, because color alone does not cover it.
/* caret-color only colors the caret, not the text itself */
.search-field {
background: #0f172a;
color: #e2e8f0;
caret-color: #c4b5fd;
border: 1px solid #334155;
border-radius: 0.5rem;
padding: 0.5rem 0.75rem;
}
/* contenteditable areas benefit from this too */
[contenteditable="true"] {
caret-color: #7c3aed;
}
4. Combining both in a custom form theme
A coherent form theme only emerges once accent-color and caret-color draw from the same design token, instead of being maintained in isolation at different places in the stylesheet. A central custom property like --brand-accent can be reused in both places, so a later brand color change touches a single line in the root selector instead of being chased through every form block individually.
It is worth deliberately separating controls from text inputs: radios and checkboxes can safely glow strongly in the brand color, since they are clearly bounded shapes, while the caret often works better a bit more muted, so it does not distract from the actual content while typing. A slightly darker or lighter shade of the same palette usually works better than reusing the exact same accent color.
5. Inheritance and scoping: where each property takes effect
Both properties inherit, which is convenient in nested form structures but also error-prone. If accent-color is set on a parent fieldset, every checkbox and radio inside inherits that value automatically, as long as no more specific selector further down the stylesheet overrides it. That cuts down on repetition considerably, but can be surprising when a form section accidentally picks up the wrong accent color from an ancestor.
For deliberate scoping, it is best to set accent-color and caret-color at a meaningful context level, such as per form block or per state class like .form-danger, rather than always defining each property directly on the individual input. That keeps the cascade traceable, and a single class change on the container is enough to recolor an entire form segment.
6. Contrast, focus indicators and forced-colors mode
Anyone who changes the accent color of checkboxes and radios automatically takes on responsibility for sufficient contrast against the background. The WCAG guidelines require a minimum contrast of 3:1 for UI components against the surrounding area, and an accent color that is too light on a white background can fall below that threshold, even if it worked fine on a dark background.
In forced-colors mode, for example Windows high-contrast mode, the operating system overrides both accent-color and caret-color with system-wide contrast colors, so users with visual impairments get a consistent appearance across every application. Custom values are deliberately ignored there, which is not a bug but intended behavior that should only be circumvented with forced-color-adjust in genuine edge cases.
7. Browser support and fallback strategies
Both properties now count as broadly supported across every current version of Chrome, Firefox, Safari and Edge, so most production projects no longer need any fallback logic at all. In older browser versions that do not recognize either property, the corresponding declaration block is simply ignored and the control falls back to the browser's default appearance, without breaking the layout or throwing an error.
For projects targeting very old browsers, it is still worth a quick check against the compatibility tables before relying on accent-color as the only visual cue for important status, such as a selected radio in a payment form. An additional visual signal, like a visible border or a checkmark icon in the active state, keeps the form usable even on the rare occasion the accent color does not apply.
8. Practical example: a checkout form with a coherent color scheme
A checkout form typically brings both property types together: radio buttons for the payment method, checkboxes for terms acceptance and newsletter opt-in, plus text fields for address and payment details. A coherent theme sets accent-color to the brand color for every selection element and a slightly muted variant as caret-color in the text fields, so the caret stays present without dominating.
The snippet below shows how both properties draw on a shared set of custom properties, so a future brand color redesign happens in exactly one place in the stylesheet instead of being manually chased through every individual form block.
<style>
:root {
--brand-accent: #7c3aed;
--brand-accent-soft: #a78bfa;
}
.checkout-form input[type="radio"],
.checkout-form input[type="checkbox"] {
accent-color: var(--brand-accent);
}
.checkout-form input[type="text"],
.checkout-form input[type="email"] {
caret-color: var(--brand-accent-soft);
}
</style>
<form class="checkout-form">
<label><input type="radio" name="payment" checked> Credit card</label>
<label><input type="radio" name="payment"> Invoice</label>
<input type="email" placeholder="Email address">
<label><input type="checkbox" required> Accept terms</label>
</form>
9. Common mix-ups and how to avoid them
The most common mistake is assuming caret-color also affects the border color of a focused field, it does not, that is the job of outline-color or border-color. Just as often, developers expect accent-color to apply to a plain text input, but the element simply has no accent state for the browser to color.
A second pitfall is expecting accent-color to take full visual control over a checkbox, including its shape or size. The property only affects the color of the control the operating system already draws; for structural changes, appearance: none with fully custom markup remains the only option.
| Property | Affected elements | What gets colored | Inherited |
|---|---|---|---|
accent-color |
checkbox, radio, range, progress | Accent area of the control | Yes |
caret-color |
input, textarea, contenteditable | Blinking text caret | Yes |
color |
all text elements | Text color (caret fallback) | Yes |
outline-color |
focusable elements | Focus ring | No |
::selection |
selected text | Text selection background | No, pseudo-element |
Mironsoft
Modern CSS, layout architecture and rendering performance
CSS that stays maintainable instead of breaking with every change?
We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.
CSS Audit
Systematically uncovering specificity issues, cascade conflicts and unused selectors.
Architecture Refactoring
Introducing cascade layers, custom properties and design tokens cleanly.
Performance Tuning
Fixing layout thrashing, expensive selectors and rendering bottlenecks.
10. Summary
accent-color vs. caret-color: The Essentials at a Glance
accent-color
Colors native checkboxes, radios, range and progress, builds on OS rendering, stays accessible.
caret-color
Colors only the caret in text fields and contenteditable, independent of color, matches text color by default.
Shared foundation
Drive both properties from the same custom properties so a brand color change only touches one place.
Accessibility
Keep a minimum 3:1 contrast for accent-color, forced-colors mode deliberately overrides custom values with system colors.