The outline-offset property controls the distance between an element's outline and its border edge. Here's how to use it.
Basic Usage#
1/* Positive offset - outline moves outward */
2.element {
3 outline: 2px solid blue;
4 outline-offset: 4px;
5}
6
7/* Negative offset - outline moves inward */
8.inset-outline {
9 outline: 2px solid red;
10 outline-offset: -4px;
11}
12
13/* Zero offset - outline sits on border edge */
14.no-offset {
15 outline: 2px solid green;
16 outline-offset: 0;
17}Focus Indicators#
1/* Accessible focus with offset */
2button:focus-visible {
3 outline: 2px solid #3b82f6;
4 outline-offset: 2px;
5}
6
7/* Different focus styles */
8.button-primary:focus-visible {
9 outline: 3px solid currentColor;
10 outline-offset: 3px;
11}
12
13.button-secondary:focus-visible {
14 outline: 2px dashed #6b7280;
15 outline-offset: 4px;
16}
17
18/* Focus visible only for keyboard */
19a:focus {
20 outline: none;
21}
22
23a:focus-visible {
24 outline: 2px solid #3b82f6;
25 outline-offset: 2px;
26}Link Styling#
1/* Links with visible focus */
2a {
3 color: #2563eb;
4 text-decoration: underline;
5}
6
7a:focus-visible {
8 outline: 2px solid currentColor;
9 outline-offset: 3px;
10 border-radius: 2px;
11}
12
13/* Navigation links */
14.nav-link {
15 padding: 0.5rem 1rem;
16 text-decoration: none;
17}
18
19.nav-link:focus-visible {
20 outline: 2px solid #3b82f6;
21 outline-offset: -2px; /* Inside padding */
22}
23
24/* Inline links in text */
25.content a:focus-visible {
26 outline: 2px solid #3b82f6;
27 outline-offset: 2px;
28 text-decoration: none;
29}Cards and Containers#
1/* Card with focus state */
2.card {
3 padding: 1.5rem;
4 border: 1px solid #e5e7eb;
5 border-radius: 8px;
6 transition: box-shadow 0.2s;
7}
8
9.card:focus-within {
10 outline: 2px solid #3b82f6;
11 outline-offset: 2px;
12}
13
14/* Interactive card */
15.card-link {
16 display: block;
17 text-decoration: none;
18 color: inherit;
19}
20
21.card-link:focus-visible {
22 outline: 3px solid #3b82f6;
23 outline-offset: 4px;
24 border-radius: 8px;
25}
26
27/* Negative offset for tight containers */
28.compact-card:focus-visible {
29 outline: 2px solid #3b82f6;
30 outline-offset: -4px;
31}Form Elements#
1/* Input focus */
2input,
3textarea,
4select {
5 border: 1px solid #d1d5db;
6 border-radius: 4px;
7 padding: 0.5rem;
8}
9
10input:focus,
11textarea:focus,
12select:focus {
13 outline: 2px solid #3b82f6;
14 outline-offset: 0;
15 border-color: #3b82f6;
16}
17
18/* Checkbox and radio */
19input[type="checkbox"],
20input[type="radio"] {
21 width: 1.25rem;
22 height: 1.25rem;
23}
24
25input[type="checkbox"]:focus-visible,
26input[type="radio"]:focus-visible {
27 outline: 2px solid #3b82f6;
28 outline-offset: 2px;
29}
30
31/* Custom checkbox wrapper */
32.checkbox-wrapper:focus-within {
33 outline: 2px solid #3b82f6;
34 outline-offset: 4px;
35 border-radius: 4px;
36}Buttons#
1/* Primary button */
2.btn-primary {
3 background: #3b82f6;
4 color: white;
5 border: none;
6 padding: 0.75rem 1.5rem;
7 border-radius: 6px;
8}
9
10.btn-primary:focus-visible {
11 outline: 2px solid #1d4ed8;
12 outline-offset: 2px;
13}
14
15/* Ghost button */
16.btn-ghost {
17 background: transparent;
18 border: 2px solid currentColor;
19 padding: 0.75rem 1.5rem;
20 border-radius: 6px;
21}
22
23.btn-ghost:focus-visible {
24 outline: 2px solid currentColor;
25 outline-offset: 4px;
26}
27
28/* Icon button */
29.btn-icon {
30 width: 2.5rem;
31 height: 2.5rem;
32 border-radius: 50%;
33 display: flex;
34 align-items: center;
35 justify-content: center;
36}
37
38.btn-icon:focus-visible {
39 outline: 2px solid #3b82f6;
40 outline-offset: 3px;
41}Animation and Transitions#
1/* Animated outline offset */
2.animated-focus {
3 outline: 2px solid transparent;
4 outline-offset: 0;
5 transition: outline-color 0.2s, outline-offset 0.2s;
6}
7
8.animated-focus:focus-visible {
9 outline-color: #3b82f6;
10 outline-offset: 4px;
11}
12
13/* Pulse animation on focus */
14@keyframes focus-pulse {
15 0%, 100% {
16 outline-offset: 2px;
17 }
18 50% {
19 outline-offset: 4px;
20 }
21}
22
23.pulse-focus:focus-visible {
24 outline: 2px solid #3b82f6;
25 animation: focus-pulse 1s infinite;
26}
27
28/* Grow on focus */
29.grow-outline:focus-visible {
30 outline: 2px solid #3b82f6;
31 outline-offset: 0;
32 animation: grow-outline 0.2s forwards;
33}
34
35@keyframes grow-outline {
36 to {
37 outline-offset: 4px;
38 }
39}High Contrast Mode#
1/* Ensure visibility in high contrast */
2@media (prefers-contrast: high) {
3 :focus-visible {
4 outline: 3px solid currentColor;
5 outline-offset: 3px;
6 }
7
8 /* Stronger focus for buttons */
9 button:focus-visible {
10 outline-width: 4px;
11 outline-offset: 4px;
12 }
13}
14
15/* Forced colors mode */
16@media (forced-colors: active) {
17 :focus-visible {
18 outline: 3px solid CanvasText;
19 outline-offset: 2px;
20 }
21}Images and Media#
1/* Focusable images */
2img[tabindex]:focus-visible {
3 outline: 3px solid #3b82f6;
4 outline-offset: 4px;
5}
6
7/* Linked images */
8a > img {
9 display: block;
10}
11
12a:focus-visible > img {
13 outline: 3px solid #3b82f6;
14 outline-offset: 4px;
15}
16
17/* Video player */
18video:focus-visible {
19 outline: 3px solid #3b82f6;
20 outline-offset: 4px;
21}
22
23/* Figure with caption */
24figure:focus-within {
25 outline: 2px solid #3b82f6;
26 outline-offset: 8px;
27}Negative Offset Uses#
1/* Inset focus ring */
2.inset-focus:focus-visible {
3 outline: 2px solid rgba(59, 130, 246, 0.8);
4 outline-offset: -4px;
5}
6
7/* Button with inset focus */
8.btn-inset {
9 padding: 1rem 2rem;
10 background: #f3f4f6;
11 border: none;
12}
13
14.btn-inset:focus-visible {
15 outline: 2px solid #3b82f6;
16 outline-offset: -6px;
17}
18
19/* Card with inset indicator */
20.card-inset:focus-visible {
21 outline: 3px solid #3b82f6;
22 outline-offset: -8px;
23 border-radius: 4px;
24}Skip Links#
1/* Skip to content link */
2.skip-link {
3 position: absolute;
4 top: -100%;
5 left: 50%;
6 transform: translateX(-50%);
7 padding: 1rem 2rem;
8 background: #1f2937;
9 color: white;
10 text-decoration: none;
11 border-radius: 0 0 8px 8px;
12 z-index: 1000;
13}
14
15.skip-link:focus {
16 top: 0;
17 outline: 3px solid #fbbf24;
18 outline-offset: 4px;
19}Custom Focus Styles#
1/* Double ring effect */
2.double-ring:focus-visible {
3 outline: 2px solid white;
4 outline-offset: 2px;
5 box-shadow: 0 0 0 4px #3b82f6;
6}
7
8/* Gradient-like effect with multiple elements */
9.focus-wrapper {
10 position: relative;
11}
12
13.focus-wrapper:focus-within::after {
14 content: '';
15 position: absolute;
16 inset: -6px;
17 border: 2px solid #3b82f6;
18 border-radius: 8px;
19 pointer-events: none;
20}
21
22/* Glow effect */
23.glow-focus:focus-visible {
24 outline: 2px solid #3b82f6;
25 outline-offset: 2px;
26 box-shadow: 0 0 20px rgba(59, 130, 246, 0.5);
27}Dark Mode#
1/* Light mode focus */
2:root {
3 --focus-color: #3b82f6;
4 --focus-offset: 2px;
5}
6
7/* Dark mode focus */
8@media (prefers-color-scheme: dark) {
9 :root {
10 --focus-color: #60a5fa;
11 --focus-offset: 3px;
12 }
13}
14
15:focus-visible {
16 outline: 2px solid var(--focus-color);
17 outline-offset: var(--focus-offset);
18}
19
20/* Dark mode specific adjustments */
21.dark :focus-visible {
22 outline-color: #93c5fd;
23 outline-offset: 3px;
24}Best Practices#
Accessibility:
✓ Use :focus-visible for keyboard
✓ Sufficient contrast ratio
✓ Minimum 2px outline width
✓ Visible in all color modes
Positioning:
✓ Positive offset for clarity
✓ Negative offset for tight spaces
✓ Consider border-radius
✓ Account for spacing
Animation:
✓ Respect prefers-reduced-motion
✓ Keep transitions short
✓ Subtle offset changes
✓ Don't delay visibility
Avoid:
✗ Removing focus outlines
✗ Very thin outlines
✗ Low contrast colors
✗ Hiding focus states
Conclusion#
The outline-offset property provides precise control over focus indicator positioning. Use positive values to create space between the element and its outline, negative values for inset effects, and combine with transitions for smooth animations. Always ensure focus indicators are visible and meet accessibility guidelines - typically at least 2px width with sufficient color contrast.