Docs
Search

Modal

This page is currently under construction
Lism UI (@lism-css/ui) is still in preparation.

A component for displaying modals using the dialog element.

Overview

↓
Preview

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

<Modal.OpenBtn modalId="modal-01" className="-bd -px:15 -py:5 -bdrs:10">Open Modal 01</Modal.OpenBtn>
<Modal.Root id="modal-01" aria-labelledby="modal-01-title" p="30">
<Modal.Inner layout="stack" pos="relative" max-sz="m" mx="auto" p="35" bdrs="30" bxsh="30">
<Modal.CloseBtn modalId="modal-01" autofocus pos="absolute" t="0" r="0" z="1" fz="xl" p="10" m="10" />
<Modal.Body layout="stack" g="30" util="trimAll">
<h2 className="-fz:l -fw:bold" id="modal-01-title">Modal Title</h2>
<p>Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.</p>
</Modal.Body>
</Modal.Inner>
</Modal.Root>

Add an id to <Modal.Root>, and pass the same modalId to <Modal.OpenBtn> / <Modal.CloseBtn> to wire up the open/close triggers.

  • Do not change the display value of the dialog element.
  • Due to animation issues with ::backdrop, this component assumes the dialog covers the full viewport width with a background color.
  • To announce the modal’s name to screen readers, specify aria-labelledby on <Modal.Root> pointing to the title element (e.g. h2). For modals without a visible title, use aria-label instead.

Styles

The Modal base styles are defined in the following CSS.

_style.css
/*
 * dialog で実装.
 *   Memo: ::backdrop のアニメーションはFirefoxで動かない
 */
@layer lism-block {
  .b--modal {
    --flow: 0 !important; /* flow直下にきても影響しないように */
    --duration: var(--modal-duration, 0.3s);
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    overflow: unset;
    background: var(--backdrop-bg, rgb(0 0 0 / 0.5));
    backdrop-filter: var(--modal-blur, blur(4px));
    transition-duration: var(--duration);
    transition-property: opacity;
  }
  .b--modal::backdrop {
    background: none;
  }
  .b--modal[open] {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .b--modal_inner {
    --offset: 0 0; /* アニメーション用 */
    background-color: var(--base);
    transition: translate var(--duration);
    max-height: 100%;
  }

  .b--modal_openBtn,
  .b--modal_closeBtn {
    display: inline-flex;
    align-items: center;
  }

  .b--modal:not([data-is-open]) {
    opacity: 0;
  }
  .b--modal:not([data-is-open]) > .b--modal_inner {
    translate: var(--offset);
  }

  /* 減速設定時はアニメーションを無効化(duration プロップ由来の inline style よりも優先させるため !important) */
  @media (prefers-reduced-motion: reduce) {
    .b--modal {
      --duration: 0s !important;
    }
  }
}

The full source code is available on GitHub.

Usage

Provided as Modal from the @lism-css/ui package.

Import

import { Modal } from '@lism-css/ui/react';

<Modal.Root>, <Modal.Inner>, <Modal.Body>, <Modal.OpenBtn>, and <Modal.CloseBtn> are available.

Props

Prop Description
id The id attribute is required on Modal (b--modal).
<Modal.Root>
duration
Sets the duration of the modal open/close animation. Output as the --duration variable.
<Modal.Inner>
layout
Specifies the layout component for __inner.
<Modal.Inner>
offset
Offset value to shift the position of __inner when hidden.
<Modal.OpenBtn>
modalId
Output as data-modal-open. Specifies the modal id on the trigger element that opens the modal.
<Modal.CloseBtn>
modalId
Output as data-modal-close. Specifies the modal id on the trigger element that closes the modal.
<Modal.CloseBtn>
icon
Specifies the icon displayed when no children are passed. (Default: x)
<Modal.CloseBtn>
srText
Specifies the text output for screen readers when the icon is displayed. (Default: Close)

Examples

To make <Modal.Body> scrollable, specify ov-y="auto". Place any content that should always remain visible before or after it.

Example with long content

↓
Modal example

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut.

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut.

Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint. Occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis undeomnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.

<Modal.OpenBtn modalId="modal-02" className="-bd -px:15 -py:5 -bdrs:10">Open Modal 02</Modal.OpenBtn>
<Modal.Root id="modal-02" aria-labelledby="modal-02-title" isContainer px="30" py="50">
<Modal.Inner layout="stack" max-sz="s" mx="auto" bdrs="20" bxsh="40">
<Flex ai="center" jc="between" py="15" bd-b>
<Inline as="h2" id="modal-02-title" fz="l" fw="bold" hl="s" ms="30">
<Fragment>Modal Header</Fragment>
</Inline>
<Modal.CloseBtn modalId="modal-02" autofocus fz="xl" p="10" mx="15" />
</Flex>
<Modal.Body layout="flow" px="30" py="20" ov-y="auto">
<DummyText />
<Box ar="16/9" bgc="base-2" bd />
<DummyText length="l" />
<DummyText length="s" />
<DummyText length="m" />
<Box ar="16/9" bgc="base-2" bd />
<DummyText length="xl" />
</Modal.Body>
<Flex jc="end" px="30" py="15" bd-t>
<Modal.CloseBtn modalId="modal-02" bgc="text" c="base" hl="s" px="15" py="10" bd="none" bdrs="10">
<Fragment>Cancel</Fragment>
</Modal.CloseBtn>
</Flex>
</Modal.Inner>
</Modal.Root>

Drawer menu example

Clicking a same-page link (such as #id) inside the modal jumps to the target and closes the modal.

↓
Drawer menu example
import { MenuIcon } from '@lism-css/icons/react';
<Modal.OpenBtn modalId="modal-03" g="5" fz="s">
<Icon icon={MenuIcon} fz="l" /><span>MENU</span>
</Modal.OpenBtn>
<Modal.Root id="modal-03" aria-label="Menu">
<Modal.Inner layout="stack" max-w="24rem" h="100%" bxsh="40" offset="-100px 0">
<Flex bd-b ai="center" jc="between" p="20">
<Inline fw="bold">MENU</Inline>
<Modal.CloseBtn modalId="modal-03" autofocus fz="xl" p="5" />
</Flex>
<Modal.Body ov-y="auto">
<nav aria-label="Main menu">
<NavMenu.Root bd-b itemP="1em">
<NavMenu.Item>
<NavMenu.Link href="#menu-link01">Menu item 1</NavMenu.Link>
</NavMenu.Item>
<NavMenu.Item>
<NavMenu.Link href="#menu-link02">Menu item 2</NavMenu.Link>
</NavMenu.Item>
<NavMenu.Item>
<NavMenu.Link href="#menu-link03">Menu item 3</NavMenu.Link>
</NavMenu.Item>
<NavMenu.Item>
<NavMenu.Link href="#menu-link04">Menu item 4</NavMenu.Link>
</NavMenu.Item>
</NavMenu.Root>
</nav>
</Modal.Body>
</Modal.Inner>
</Modal.Root>

© 2026 Lism CSS.