Scroll Area

GitHub
Augments native scroll functionality for custom, cross-browser styling.
Tags
v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1
<script setup lang="ts">
import { AScrollAreaRoot, AScrollAreaScrollbar, AScrollAreaThumb, AScrollAreaViewport } from 'akar';

const tags = Array.from({ length: 50 }).map((_, i, a) => `v1.2.0-beta.${a.length - i}`);
</script>

<template>
  <AScrollAreaRoot
    class="border border-border rounded-lg bg-background h-[225px] w-[200px] shadow-sm relative overflow-hidden"
    style="--scrollbar-size: 10px"
  >
    <div class="h-6 w-full top-0 absolute z-10 from-transparent to-white bg-gradient-to-t" />
    <AScrollAreaViewport class="rounded h-full w-full">
      <div class="px-5 py-[15px]">
        <div class="text-sm color-primary leading-[18px] font-semibold">
          Tags
        </div>
        <div
          v-for="tag in tags"
          :key="tag"
          class="text-xs leading-[18px] mt-2.5 pt-2.5 border-t border-t-border"
        >
          {{ tag }}
        </div>
      </div>
    </AScrollAreaViewport>
    <AScrollAreaScrollbar
      class="p-0.5 bg-background-elevated flex select-none transition-colors duration-[160ms] ease-out z-20 touch-none hover:bg-background-accented data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5"
      orientation="vertical"
    >
      <AScrollAreaThumb
        class="rounded-[10px] bg-primary flex-1 relative before:(h-full min-h-[44px] min-w-[44px] w-full content-empty left-1/2 top-1/2 absolute -translate-x-1/2 -translate-y-1/2)"
      />
    </AScrollAreaScrollbar>
    <AScrollAreaScrollbar
      class="p-0.5 bg-background-elevated flex select-none transition-colors duration-[160ms] ease-out touch-none hover:bg-background-accented data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5"
      orientation="horizontal"
    >
      <AScrollAreaThumb
        class="rounded-[10px] bg-primary flex-1 relative before:(h-full min-h-[44px] min-w-[44px] w-full content-empty left-1/2 top-1/2 absolute -translate-x-1/2 -translate-y-1/2)"
      />
    </AScrollAreaScrollbar>

    <div class="h-6 w-full bottom-0 absolute z-10 from-transparent to-white bg-gradient-to-b" />
  </AScrollAreaRoot>
</template>

Features

  • Scrollbar sits on top of the scrollable content, taking up no space.
  • Scrolling is native; no underlying position movements via CSS transformations.
  • Shims pointer behaviors only when interacting with the controls, so keyboard controls are unaffected.
  • Supports Right to Left direction.

Anatomy

Import all parts and piece them together.

<script setup>
import { AScrollAreaRoot, AScrollAreaScrollbar, AScrollAreaThumb, AScrollAreaViewport } from 'akar';
</script>

<template>
  <AScrollAreaRoot>
    <AScrollAreaViewport />
    <AScrollAreaScrollbar orientation="horizontal">
      <AScrollAreaThumb />
    </AScrollAreaScrollbar>
    <AScrollAreaScrollbar orientation="vertical">
      <AScrollAreaThumb />
    </AScrollAreaScrollbar>
    <AScrollAreaCorner />
  </AScrollAreaRoot>
</template>

API Reference

Root

Contains all the parts of a scroll area.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

dir'ltr' | 'rtl'

The reading direction of the combobox when applicable.
If omitted, inherits globally from AConfigProvider or assumes LTR (left-to-right) reading mode.

scrollHideDelay600number

If type is set to either scroll or hover, this prop determines the length of time, in milliseconds,
before the scrollbars are hidden after the user stops interacting with scrollbars.

type'hover''always' | 'scroll' | 'hover' | 'auto'

Describes the nature of scrollbar visibility, similar to how the scrollbar preferences in MacOS control visibility of native scrollbars.

auto - means that scrollbars are visible when content is overflowing on the corresponding orientation.
always - means that scrollbars are always visible regardless of whether the content is overflowing.
scroll - means that scrollbars are visible when the user is scrolling along its corresponding orientation.
hover - when the user is scrolling along its corresponding orientation and when the user is hovering over the scroll area.

Viewport

The viewport area of the scroll area.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

noncestring

Will add nonce attribute to the style tag which can be used by Content Security Policy.
If omitted, inherits globally from AConfigProvider.

Scrollbar

The vertical scrollbar. Add a second Scrollbar with an orientation prop to enable horizontal scrolling.

Built with Presence component - supports any animation techniques while maintaining access to presence emitted events.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

forceMountboolean

Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.

orientation'vertical''horizontal' | 'vertical'

The orientation of the scrollbar

Data Attributes

Attribute Value
[data-orientation]'vertical' | 'horizontal'
[data-state]'visible' | 'hidden'

Thumb

The thumb to be used in AScrollAreaScrollbar.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data Attributes

Attribute Value
[data-state]'visible' | 'hidden'

Corner

The corner where both vertical and horizontal scrollbars meet.

Props

Prop Default Type
as'div'APrimitiveAsTag | Component

The element or component this component should render as. Can be overwritten by asChild.

asChildboolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Examples

Custom Scroll

Use the exposed viewport to modify / or set the scroll position outside default methods

<script setup lang="ts">
import { AScrollAreaRoot, AScrollAreaScrollbar, AScrollAreaThumb, AScrollAreaViewport } from 'akar'

const scrollArea = useTemplateRef('scrollArea')
function scrollToBottom() {
  const viewport = scrollArea.value?.viewport
  if (viewport) {
    const top = scrollArea.value?.$el.scrollHeight
    container.scrollTo({
      top,
      behavior: 'smooth'
    })
  }
}
</script>

<template>
  <AScrollAreaRoot ref="scrollArea">
    <AScrollAreaViewport />
    <AScrollAreaScrollbar orientation="horizontal">
      <AScrollAreaThumb />
    </AScrollAreaScrollbar>
    <AScrollAreaScrollbar orientation="vertical">
      <AScrollAreaThumb />
    </AScrollAreaScrollbar>
    <AScrollAreaCorner />
  </AScrollAreaRoot>
</template>

Accessibility

In most cases, it's best to rely on native scrolling and work with the customization options available in CSS. When that isn't enough, AScrollArea provides additional customizability while maintaining the browser's native scroll behavior (as well as accessibility features, like keyboard scrolling).

Keyboard Interactions

Scrolling via keyboard is supported by default because the component relies on native scrolling. Specific keyboard interactions may differ between platforms, so we do not specify them here or add specific event listeners to handle scrolling via key events.