CSS scroll-margin

Explore how scroll-margin expands the area used to bring an element into view without occupying layout space. Apply one shared value or adjust every side independently.

Ask AI

CSS scroll-margin

Response generated with openai/gpt-5.4-nano. AI can make mistakes. Always review the result.
What to look for

Align card 05 and change the value. Its border moves away from the scrollport while the grid keeps the same gap.

Dotted area: invisible zone that aligns before the card

Anchor 1

Focus this target to bring its expanded area into view.

Anchor 2

Focus this target to bring its expanded area into view.

Anchor 3

Focus this target to bring its expanded area into view.

Anchor 4

Focus this target to bring its expanded area into view.

Test target

Anchor 5

Focus this target to bring its expanded area into view.

Anchor 6

Focus this target to bring its expanded area into view.

Anchor 7

Focus this target to bring its expanded area into view.

Anchor 8

Focus this target to bring its expanded area into view.

Anchor 9

Focus this target to bring its expanded area into view.

HTML
<div class="scrollport" aria-label="Interactive scroll-margin area" tabindex="0">
  <article
    class="snap-target"
    style="--target-color: #a7df9b"
    tabindex="0"
  >
    <h2>Anchor 1</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #f6bd60"
    tabindex="0"
  >
    <h2>Anchor 2</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #c7a6ff"
    tabindex="0"
  >
    <h2>Anchor 3</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #8ecae6"
    tabindex="0"
  >
    <h2>Anchor 4</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #ffb38a"
    tabindex="0"
  >
    <h2>Anchor 5</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #72d6c9"
    tabindex="0"
  >
    <h2>Anchor 6</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #f7a6c4"
    tabindex="0"
  >
    <h2>Anchor 7</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #ffd166"
    tabindex="0"
  >
    <h2>Anchor 8</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="snap-target"
    style="--target-color: #90caf9"
    tabindex="0"
  >
    <h2>Anchor 9</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
</div>
Tailwind CSS
Some classes with arbitrary values can be replaced by native classes, depending on the value and your Tailwind CSS configuration.
<div class="grid grid-cols-[repeat(3,minmax(16rem,72%))] auto-rows-[72%] gap-20 inline-[min(100%,36rem)] block-96 m-0 p-16 overflow-auto overscroll-contain snap-both snap-mandatory" aria-label="Interactive scroll-margin area" tabindex="0">
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#a7df9b_72%,#172033)] bg-[#a7df9b]"
    tabindex="0"
  >
    <h2>Anchor 1</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#f6bd60_72%,#172033)] bg-[#f6bd60]"
    tabindex="0"
  >
    <h2>Anchor 2</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#c7a6ff_72%,#172033)] bg-[#c7a6ff]"
    tabindex="0"
  >
    <h2>Anchor 3</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#8ecae6_72%,#172033)] bg-[#8ecae6]"
    tabindex="0"
  >
    <h2>Anchor 4</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#ffb38a_72%,#172033)] bg-[#ffb38a]"
    tabindex="0"
  >
    <h2>Anchor 5</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#72d6c9_72%,#172033)] bg-[#72d6c9]"
    tabindex="0"
  >
    <h2>Anchor 6</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#f7a6c4_72%,#172033)] bg-[#f7a6c4]"
    tabindex="0"
  >
    <h2>Anchor 7</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#ffd166_72%,#172033)] bg-[#ffd166]"
    tabindex="0"
  >
    <h2>Anchor 8</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
  <article
    class="box-border grid content-end gap-2 p-5 border rounded-2xl text-[#172033] snap-start scroll-m-[16px] *:m-0 [&_h2]:text-[clamp(1.5rem,1rem_+_2vw,2.5rem)] focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#90caf9_72%,#172033)] bg-[#90caf9]"
    tabindex="0"
  >
    <h2>Anchor 9</h2>
    <p>Focus this target to bring its expanded area into view.</p>
  </article>
</div>
CSS
.scrollport {
  display: grid;
  grid-template-columns: repeat(3, minmax(16rem, 72%));
  grid-auto-rows: 72%;
  gap: 5rem;
  inline-size: min(100%, 36rem);
  block-size: 24rem;
  margin: 0;
  padding: 4rem;
  overflow: auto;
  overscroll-behavior: contain;
  scroll-snap-type: both mandatory;
}

.snap-target {
  box-sizing: border-box;
  display: grid;
  align-content: end;
  gap: 0.5rem;
  padding: 1.25rem;
  border: 1px solid color-mix(in oklch, var(--target-color) 72%, #172033);
  border-radius: 1rem;
  background: var(--target-color);
  color: #172033;
  scroll-snap-align: start;
  scroll-margin: 16px;
}

.snap-target > * {
  margin: 0;
}

.snap-target h2 {
  font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem);
}

.snap-target:focus-visible {
  outline: 4px solid #172033;
  outline-offset: -8px;
}