This section covers the customization of native browser elements: text selection, scrollbars, form components, keyboard focus, and dialog.
Customizes the appearance of text selected by the user.
::selection {
background: var(--bux-selection-bg);
color: var(--bux-selection-color);
text-shadow: var(--bux-selection-text-shadow);
}By default, selection uses the inverted theme colors (dark background on light text, or reversed in dark mode). Configurable via CSS variables.
Scrollbars are styled differently depending on the rendering engine.
scrollbar-color is scoped to Firefox via @supports to prevent it from overriding WebKit pseudo-elements in other browsers:
@supports (-moz-appearance: none) {
html {
scrollbar-color: var(--bux-scrollbar-thumb) var(--bux-scrollbar-track);
scrollbar-width: auto;
}
}::-webkit-scrollbar {
background: var(--bux-scrollbar);
height: var(--bux-scrollbar-horizontal-height);
width: var(--bux-scrollbar-vertical-width);
}
::-webkit-scrollbar-button { display: none; }
::-webkit-scrollbar-track {
background-color: var(--bux-scrollbar-track);
}
::-webkit-scrollbar-thumb {
background-color: var(--bux-scrollbar-thumb);
border-radius: calc(var(--bux-scrollbar-vertical-width) / 2);
}
::-webkit-scrollbar-thumb:hover {
background-color: var(--bux-scrollbar-thumb-hover);
}
::-webkit-scrollbar-corner { background: transparent; }Dimensions, colors, and hover behavior are all configurable via scrollbar variables.
::placeholder {
color: var(--bux-placeholder-color);
}Applies the theme primary color to the input cursor in editable fields:
input,
textarea,
[contenteditable] {
caret-color: var(--bux-color-primary);
}Applies the primary color to form elements that support accent-color:
input[type="checkbox"],
input[type="radio"],
input[type="range"],
meter,
select {
accent-color: var(--bux-color-primary);
}
progress {
accent-color: var(--bux-progress-value-bg);
}Customizes the range thumb in WebKit and Firefox:
input[type="range"]::-webkit-slider-thumb,
input[type="range"]::-moz-range-thumb {
background: var(--bux-color-primary);
border: none;
}Validation styles apply only after user interaction with the field, thanks to :user-valid and :user-invalid (unlike :valid / :invalid which apply on page load):
input:user-valid,
textarea:user-valid,
select:user-valid {
background-color: var(--bux-valid-bg-color);
border-color: var(--bux-valid-border-color);
}
input:user-invalid,
textarea:user-invalid,
select:user-invalid {
background-color: var(--bux-invalid-bg-color);
border-color: var(--bux-invalid-border-color);
}
input:user-invalid::placeholder,
textarea:user-invalid::placeholder {
color: var(--bux-invalid-placeholder-color);
}
:user-valid/:user-invalidrequire Chrome 119+, Firefox 88+, Safari 16.5+.
Harmonizes the native appearance in WebKit and Firefox:
progress::-webkit-progress-bar {
background-color: var(--bux-progress-bar-bg);
border-radius: 8px;
}
progress::-webkit-progress-value {
background-color: var(--bux-progress-value-bg);
border-radius: 8px;
}
progress::-moz-progress-bar {
background-color: var(--bux-progress-value-bg);
}In Firefox,
::-moz-progress-bartargets the filled portion (the value), not the track. Theprogresselement itself serves as the track in Gecko.
:focus {
outline: none;
}A visible outline is shown only during keyboard navigation, thanks to :focus-visible:
:focus-visible {
outline: 2px solid var(--bux-color-primary);
outline-offset: 2px;
}- Keyboard users have a clear visual cue.
- Mouse users do not see an outline after clicking.
- In Windows High Contrast mode (
forced-colors), the outline is replaced by theHighlightsystem color. See User Preferences.
dialog {
background: var(--bux-page-bg);
border: none;
color: var(--bux-page-color);
margin: auto;
max-width: 100%;
padding: 0;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}The dialog inherits theme colors and is centered by default. The backdrop is semi-transparent.
A native animation (fade + slide) is applied on open via @starting-style, only if the user has not enabled reduced motion:
@media (prefers-reduced-motion: no-preference) {
dialog {
opacity: 1;
transform: translateY(0);
transition:
display 0.25s allow-discrete,
opacity 0.25s,
overlay 0.25s allow-discrete,
transform 0.25s;
}
@starting-style {
dialog[open] {
opacity: 0;
transform: translateY(-8px);
}
}
dialog::backdrop {
transition:
background-color 0.25s,
display 0.25s allow-discrete,
overlay 0.25s allow-discrete;
}
@starting-style {
dialog[open]::backdrop {
background-color: rgba(0, 0, 0, 0);
}
}
}@starting-styledefines the dialog state before opening (transparent, shifted upward).allow-discreteondisplayandoverlayenables transitions on discrete properties, so the element remains visible during the closing animation.