caret-shape CSS property

Limited availability

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.

The caret-shape CSS property sets the shape of the insertion caret, the visible marker that appears in editable elements to indicate where the next character will be inserted or deleted.

Try it

caret-shape: auto;
caret-shape: bar;
caret-shape: block;
caret-shape: underscore;
<section class="default-example container" id="default-example">
  <div>
    <label for="example-element">Edit text field:</label>
    <input id="example-element" type="text" value="Sample text">
  </div>
</section>
div {
  text-align: left;
}

#example-element {
  font-size: 1.2rem;
  padding: 8px;
  width: 300px;
}

Syntax

css
/* Keyword values */
caret-shape: auto;
caret-shape: bar;
caret-shape: block;
caret-shape: underscore;

/* Global values */
caret-shape: inherit;
caret-shape: initial;
caret-shape: revert;
caret-shape: revert-layer;
caret-shape: unset;

Values

auto

The default value. The browser determines the caret shape. This typically follows platform conventions and may change based on context.

bar

The caret appears as a thin vertical line at the insertion point, positioned between characters rather than over them.

block

The caret appears as a rectangle that overlaps the next character after the insertion point. If no character follows, it appears after the last character.

underscore

The caret appears as a thin horizontal line underneath the next character after the insertion point. If no character follows, it appears after the last character.

Description

The insertion caret is the blinking cursor that indicates where text will be inserted when typing. Different caret shapes can provide visual feedback about the current editing mode or offer visual customization.

Editing modes and caret shapes

Text editors typically operate in one of two modes:

  • Insert mode: New characters are inserted at the caret position, pushing existing text to the end of the line. This is the default behavior in most modern applications.
  • Overtype mode (also called "overwrite mode"): New characters replace existing characters at the caret position instead of being inserted between them. This mode is often toggled with the Insert key.

Different caret shapes have traditional uses, for example:

  • Bar carets are positioned between characters and are most common in modern interfaces.
  • Block carets overlay the next character and are often used in terminal applications or to indicate overtype mode.
  • Underscore carets appear below characters and can be useful for certain design aesthetics, such as mimicking typewriter or underline text input styles.

Caret positioning and behavior

The caret-shape property affects how the caret is visually rendered but doesn't change its logical position in the text. The caret always represents the insertion point between characters, regardless of its visual shape.

Interaction with writing modes

The caret shape adapts to the writing-mode of the text. In vertical writing modes, bar carets become horizontal, and underscore carets position themselves appropriately relative to the text direction.

Formal definition

Initial valueauto
Applies toText or elements that accept text input
Inheritedyes
Computed valueas specified
Animation typeby computed value type

Formal syntax

caret-shape = 
auto |
bar |
block |
underscore

Examples

Retro terminal with animated caret

This example shows how to create a vintage terminal interface using caret-shape: block with animated caret color, replacing the old technique of using borders.

The key part is using the modern caret properties instead of the old border-based technique. We set the caret to block shape, disable the default blinking, and create our own custom animation.

HTML

html
<label for="terminal">Enter a command</label>
<div class="old-screen">
  <span>></span>
  <textarea id="terminal" class="terminal-input"></textarea>
</div>

CSS

css
.terminal-input {
  caret-shape: block;
  caret-animation: manual;
  animation: old-caret 2s infinite;
}

@keyframes old-caret {
  0%,
  50% {
    caret-color: #00ad00;
  }
  75%,
  100% {
    caret-color: transparent;
  }
}

Result

Console interface with underscore caret

This example demonstrates using caret-shape: underscore to create a console-style interface where the underscore caret complements the terminal aesthetic.

HTML

html
<label for="console">Enter a command</label>
<div class="console-demo">
  <div class="console-output">
    <p>user@host:css-ui-4 $ ls -a</p>
    <p>. .. Overview.bs Overview.html</p>
  </div>
  <div class="console-input">
    <span class="prompt">user@host:css-ui-4 $ </span>
    <input type="text" id="console" class="console" value="cd" />
  </div>
</div>

CSS

css
.console {
  caret-shape: underscore;
}

Result

Specifications

Specification
CSS Basic User Interface Module Level 4
# propdef-caret-shape

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
caret-shape
Experimental
Chrome – Full support
Chrome 144 (Release date: 2026-01-13)
footnote Full support
Edge – Full support
Edge 144 (Release date: 2026-01-21)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 128 (Release date: 2026-02-26)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 144 (Release date: 2026-01-13)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 95 (Release date: 2026-02-11)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – Full support
WebView Android 144 (Release date: 2026-01-13)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support
auto
Experimental
Chrome – Full support
Chrome 144 (Release date: 2026-01-13)
footnote Full support
Edge – Full support
Edge 144 (Release date: 2026-01-21)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 128 (Release date: 2026-02-26)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 144 (Release date: 2026-01-13)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 95 (Release date: 2026-02-11)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – Full support
WebView Android 144 (Release date: 2026-01-13)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support
bar
Experimental
Chrome – Full support
Chrome 144 (Release date: 2026-01-13)
footnote Full support
Edge – Full support
Edge 144 (Release date: 2026-01-21)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 128 (Release date: 2026-02-26)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 144 (Release date: 2026-01-13)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 95 (Release date: 2026-02-11)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – Full support
WebView Android 144 (Release date: 2026-01-13)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support
block
Experimental
Chrome – Full support
Chrome 144 (Release date: 2026-01-13)
footnote Full support
Edge – Full support
Edge 144 (Release date: 2026-01-21)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 128 (Release date: 2026-02-26)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 144 (Release date: 2026-01-13)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 95 (Release date: 2026-02-11)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – Full support
WebView Android 144 (Release date: 2026-01-13)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support
underscore
Experimental
Chrome – Full support
Chrome 144 (Release date: 2026-01-13)
footnote Full support
Edge – Full support
Edge 144 (Release date: 2026-01-21)
footnote Full support
Firefox – No support
Firefox
footnote No support
Opera – Full support
Opera 128 (Release date: 2026-02-26)
footnote Full support
Safari – No support
Safari
footnote No support
Chrome Android – Full support
Chrome Android 144 (Release date: 2026-01-13)
footnote Full support
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – Full support
Opera Android 95 (Release date: 2026-02-11)
footnote Full support
Safari on iOS – No support
Safari on iOS
footnote No support
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – Full support
WebView Android 144 (Release date: 2026-01-13)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
No support
No support
Experimental. Expect behavior to change in the future.

See also