CSS 컴포넌트 시스템 · 새 리소스

Bootstrap 디자인 시스템.

Bootstrap 5.3.8의 실제 간격 스케일, 의미 기반 색상, 반응형 그리드, 컴포넌트 API를 사용하세요. 작동하는 예약 양식, 오류 요약, 표 필터, 모달, 색상 모드 전환기를 살펴보고 문서에 소개된 코드를 재사용할 수 있습니다.

OpenDesign 가이드8개 챕터레퍼런스 항목 66개독자적 적용 가이드
01

Bootstrap 디자인 시스템 인터페이스 미리보기

예약을 필터링하고, 필드의 유효성을 검사하고, 기본 모달에서 내용을 검토한 다음 라이트 모드와 다크 모드 사이를 전환하세요.

장비 예약 · Bootstrap 5.3.8전체 예시 열기
Bootstrap 5.3.8 CSS 및 JavaScript를 기본 방식으로 로컬에서 제공합니다. 예약 데이터와 애플리케이션 동작은 예시를 위해 새로 구성했습니다. · 구현 레퍼런스
02

Bootstrap 디자인 시스템 디자인 레퍼런스

Bootstrap 5.3.8의 기본 컴파일 CSS 및 5.3 문서를 기준으로 합니다. 값은 기본값이며 반드시 따라야 하는 브랜드 규칙은 아닙니다. rem과 픽셀의 비교는 루트 크기 16px을 가정합니다. 반응형 글자 크기는 대형 화면 기준점보다 작은 화면에서 달라질 수 있습니다. 주변의 OpenDesign 페이지는 자체 타이포그래피를 유지합니다.

시맨틱 색상 및 배경 역할

출처
이름 / 규칙값 / 구성용도
--bs-primary#0d6efd 주요 동작 및 링크의 기본 색상입니다.
--bs-secondary#6c757d 보조 테마 계열입니다. 화면 크기에 따라 달라지는 본문 보조 텍스트 역할과는 다릅니다.
--bs-success#198754 긍정 상태의 기본 색상입니다. 텍스트 라벨도 함께 표시하세요.
--bs-danger#dc3545 오류 및 위험 테마의 기본 색상입니다.
--bs-warning#ffc107 경고 테마의 기본 색상입니다. 전경색과의 대비를 확인하세요.
--bs-info#0dcaf0 정보 테마의 기본 색상입니다.
--bs-body-bg#fff라이트 모드 페이지 배경입니다.
--bs-body-color#212529 라이트 모드 본문 전경색입니다.
--bs-secondary-bg#e9ecef 라이트 모드의 보조 배경입니다.
--bs-tertiary-bg#f8f9fa 라이트 모드의 절제된 패널 배경입니다.
--bs-primary-bg-subtle#cfe2ff 라이트 모드의 틴트가 적용된 주요 배경입니다.
--bs-primary-text-emphasis#052c65 primary-subtle 배경과 함께 사용하는 텍스트입니다.
--bs-border-color#dee2e6 라이트 모드 테두리 역할입니다.

본문 타이포그래피와 읽기 쉬운 위계

출처
이름 / 규칙값 / 구성용도
--bs-body-font-size1rem기본 본문 크기: 1rem, 일반적으로 16px입니다.
--bs-body-line-height1.5단위 없는 배수입니다. 일반적으로 줄 높이는 24px입니다.
--bs-body-font-weight400일반 본문 굵기입니다.
--bs-body-font-familyvar(--bs-font-sans-serif)Bootstrap에서 제공하는 시스템 UI 글꼴 스택입니다.
--bs-font-monospaceSFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace코드와 기술 값에는 고정폭 글꼴 스택을 사용합니다.

제목 크기 및 디스플레이 유틸리티

출처
이름 / 규칙값 / 구성용도
h1 / .h12.5rem대형 화면 기준점입니다. h1–h4는 기본적으로 반응형 글자 크기를 사용합니다.
h2 / .h22rem대형 화면 기준점입니다. h1–h4는 기본적으로 반응형 글자 크기를 사용합니다.
h3 / .h31.75rem대형 화면 기준점입니다. h1–h4는 기본적으로 반응형 글자 크기를 사용합니다.
h4 / .h41.5rem대형 화면 기준점입니다. h1–h4는 기본적으로 반응형 글자 크기를 사용합니다.
h5 / .h51.25rem고정된 기본 제목 크기입니다.
h6 / .h61rem고정된 기본 제목 크기입니다.
.lead1.25rem / weight 300도입부 텍스트입니다. 제목을 대신할 수 없습니다.
.small0.875em상대적으로 작은 텍스트입니다. 메타데이터에 선별적으로 사용하세요.

간격 유틸리티 체계

출처
이름 / 규칙값 / 구성용도
00m/p/gap/g 유틸리티와 함께 사용합니다. 예: p-0.
10.25remm/p/gap/g 유틸리티와 함께 사용합니다. 예: p-1.
20.5remm/p/gap/g 유틸리티와 함께 사용합니다. 예: p-2.
31remm/p/gap/g 유틸리티와 함께 사용합니다. 예: p-3.
41.5remm/p/gap/g 유틸리티와 함께 사용합니다. 예: p-4.
53remm/p/gap/g 유틸리티와 함께 사용합니다. 예: p-5.
ms / meinline start / end논리적 방향 기준입니다. 이전 Bootstrap의 ml/mr과는 다릅니다.
p-3 p-md-41rem → 1.5rem at md예제에 사용된 반응형 패딩입니다.
gap-20.5remflex/grid 자식 요소 사이의 간격입니다.

반응형 그리드 기준점

출처
이름 / 규칙값 / 구성용도
xs / .col-0기본 구간이며 xs 접두사는 사용하지 않습니다.
sm / .col-sm-576px소형 구간. .container 최대 너비 540px.
md / .col-md-768px중형 구간. .container 최대 너비 720px.
lg / .col-lg-992px대형 구간. .container 최대 너비 960px.
xl / .col-xl-1200px초대형 구간. .container 최대 너비 1140px.
xxl / .col-xxl-1400px기본 구간 중 가장 큰 크기. .container 최대 너비 1320px.
Grid columns12col-lg-7과 col-lg-5를 조합하면 한 행을 채웁니다.
Default horizontal gutter1.5rem열 양쪽에 0.75rem 패딩이 적용되며, 행은 음수 여백으로 이를 보정합니다.

테두리, 모서리 반경 및 입체감

출처
이름 / 규칙값 / 구성용도
--bs-border-width1px기본 테두리 두께입니다.
--bs-border-radius0.375rem입력 필드, 카드 및 기본 모서리에 적용되는 둥근 정도입니다.
--bs-border-radius-sm0.25rem작은 둥근 모서리입니다.
--bs-border-radius-lg0.5rem더 크게 둥근 모서리입니다.
--bs-border-radius-xl1rem넓은 배경 영역에 적용되는 둥근 모서리입니다.
--bs-border-radius-xxl2rem초대형 배경 영역에 적용되는 둥근 모서리입니다.
--bs-border-radius-pill50rem알약 모양입니다. 측정된 컴포넌트 모서리 반경은 아닙니다.
--bs-box-shadow-sm0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)은은한 입체감입니다.
--bs-box-shadow0 0.5rem 1rem rgba(0, 0, 0, 0.15)기본 입체감.
--bs-box-shadow-lg0 1rem 3rem rgba(0, 0, 0, 0.175)강한 입체감입니다. 모든 배경에 적용하지 마세요.

버튼 크기 및 상태 변수

출처
이름 / 규칙값 / 구성용도
--bs-btn-padding-x0.75rem기본 버튼 가로 패딩입니다.
--bs-btn-padding-y0.375rem기본 버튼 세로 패딩입니다.
--bs-btn-font-size1rem기본 버튼 라벨 크기입니다.
--bs-btn-line-height1.5기본 라벨 줄 높이 배수입니다.
--bs-btn-border-width1px기본 테두리 두께입니다.
--bs-btn-border-radiusvar(--bs-border-radius)기본 버튼 모서리 반경입니다.
--bs-btn-disabled-opacity0.65시각적 스타일입니다. 실제 disabled 속성도 함께 사용하세요.

라이트 및 다크 모드에서 달라지는 역할

출처
이름 / 규칙값 / 구성용도
--bs-body-bglight #fff / dark #212529페이지 배경은 data-bs-theme을 따릅니다.
--bs-body-colorlight #212529 / dark #dee2e6전경색은 배경에 맞춰 조정됩니다.
--bs-border-colorlight #dee2e6 / dark #495057테마에 따라 달라지는 테두리입니다.
--bs-primary-bg-subtlelight #cfe2ff / dark #031633틴트가 적용된 상태 배경은 모드에 따라 달라집니다.
--bs-primary-text-emphasislight #052c65 / dark #6ea8fe짝이 되는 subtle 배경과 함께 사용하세요.
data-bs-themelight | darkhtml 전역 또는 하위 영역에 설정합니다.
03

Bootstrap 디자인 시스템 전체 가이드

실제 인터페이스를 위해 이 시스템을 선택하고 적용하고 검토하는 실용 가이드.

DESIGN-bootstrap.md

완전한 안내와 구현 시작점, 소스 링크.

가이드 다운로드

Bootstrap 디자인 시스템: Bootstrap의 CSS 및 JavaScript 역할 선택

스타일시트 하나와 선택적 컴포넌트 동작

Bootstrap의 컴파일된 스타일시트는 그리드, 타이포그래피, 유틸리티 및 컴포넌트 외관을 제공합니다. JavaScript 번들은 Modal, Collapse, Dropdown 같은 인터랙티브 플러그인을 추가합니다. 스타일이 적용된 버튼에는 JavaScript가 필요하지 않지만, data-bs-toggle 모달 트리거에는 필요합니다. 작동하는 미리보기는 실제 동작 규약을 보여주기 위해 호환되는 5.3.8 스타일시트와 번들을 로컬에서 불러옵니다.

이 OpenDesign 가이드에서

예약 표 필터링, 오류 요약, 행의 로컬 추가는 애플리케이션 코드입니다. 이 차이를 명확히 하면 예약 동작을 Bootstrap 자체의 기능으로 오인하지 않고, 예시 데이터를 서비스 데이터로 바꿀 수 있습니다.

  • CSS: 레이아웃, 타이포그래피, 버튼, 입력 필드, 표 및 상태 스타일링.
  • Bootstrap JavaScript: 모달 열기, 배경 오버레이, Escape 키 및 포커스 동작.
  • 애플리케이션 JavaScript: 유효성 검사 메시지, 레코드 필터링 및 로컬 데이터 업데이트.

지원 사양 읽기

컴파일된 CSS 또는 Sass 빌드 선��

빠르게 시작하거나 표준 유틸리티 세트를 그대로 사용할 수 있는 제품을 만들려면 컴파일된 CSS를 사용하세요. 빌드 시 테마 맵, 유틸리티 생성 또는 그리드를 변경하려면 Sass 소스를 사용하세요. 런타임 CSS 사용자 지정 속성은 컴포넌트 수준의 사용자 지정에 유용하지만, 루트 색상 변수를 변경해도 사전 컴파일된 모든 변형이 다시 빌드되지는 않습니다.

scss
$primary: #3159a5;
$border-radius: .5rem;
@import "bootstrap/scss/bootstrap";

코드 참조

지원 사양 읽기

Bootstrap 디자인 시스템: 시맨틱 색상과 색상 모드 적용

상태 배경색과 전경색을 짝지으세요

예약 배지는 bg-primary-subtle과 text-primary-emphasis를 사용합니다. 이 두 속성은 서로 짝을 이루는 시맨틱 역할이므로 data-bs-theme이 변경될 때 전경색과 배경색이 함께 바뀝니다. 단순한 파란색 배경에 임의의 회색 텍스트 색상을 조합하면 이러한 관계가 사라집니다. ‘예약됨’, ‘사용 중’, ‘임시 저장’도 계속 텍스트 레이블로 표시되므로 색상만으로 의미를 전달하지 않습니다.

html
<span class="badge text-primary-emphasis bg-primary-subtle">Reserved</span>
<section data-bs-theme="dark">
  <div class="bg-body text-body border rounded p-3">Theme-scoped content</div>
</section>

코드 참조

지원 사양 읽기

컴포넌트 단위로 사용자 지정 범위를 한정하세요

사용자 지정 작업 버튼 하나에만 적용하려면 해당 버튼의 --bs-btn-* 속성을 재정의하세요. 기본 배경색뿐 아니라 호버 및 활성 상태의 값도 설정하세요. 아래 예시는 애플리케이션의 변형이며 Bootstrap 기본값이 아닙니다. 이 클래스는 대상 버튼에만 적용해 페이지의 다른 영역에 있는 모든 기본 동작 버튼까지 의도치 않게 바뀌지 않도록 하세요.

CSS
.btn-reserve {
  --bs-btn-color: #fff;
  --bs-btn-bg: #3159a5;
  --bs-btn-border-color: #3159a5;
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: #274783;
  --bs-btn-hover-border-color: #274783;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: #203a6b;
  --bs-btn-active-border-color: #203a6b;
}

코드 참조

지원 사양 읽기

Bootstrap 디자인 시스템: 실제 타이포그래피 스케일 사용

문서의 의미와 시각적 크기를 구분하세요

미리보기의 메인 제목은 h1 요소에 h3 클래스를 적용했습니다. 페이지의 주 제목이라는 의미는 유지하면서 도구에 적합한 더 작은 시각적 크기를 사용합니다. 섹션 제목은 h2 요소에 h5 스타일을 적용했습니다. Bootstrap는 요소별 기본 스타일과 이에 상응하는 제목 클래스를 모두 제공하므로 문서 제목 단계를 건너뛰지 않고도 이런 구분이 가능합니다.

기본 본문 텍스트 크기는 1rem이고 줄 높이는 1.5입니다. h1부터 h4까지의 크기는 반응형으로 조정된 다음 참조 표에 나온 값에 도달합니다. 따라서 특정 너비에서 찍은 스크린샷만으로 전체 타이포그래피 스케일을 정의할 수는 없습니다. 한 뷰포트에서 측정한 픽셀 크기를 그대로 복사하기보다 컴파일된 스타일이나 문서화된 Sass 동작을 사용하세요.

지원 사양 읽기

보조 텍스트에 테마를 고려한 역할을 부여하세요

text-body-secondary는 본문 색상 모드를 따릅니다. 장비 제목 아래에 표시되는 담당자 이름처럼 레코드를 보충하는 정보에 적합합니다. small 클래스는 주변 텍스트보다 글자 크기를 줄이므로 모든 필드 레이블에 적용하면 양식을 훑어보기 어려워집니다. 레이블은 기본 양식 크기로 유지하고, 간단한 안내와 메타데이터에만 작은 텍스트를 사용하세요.

html
<h1 class="h3">Equipment reservations</h1>
<p class="text-body-secondary">Review availability before booking.</p>
<small class="text-body-secondary">Local demonstration data</small>

코드 참조

지원 사양 읽기

Bootstrap 디자인 시스템: 간격 유틸리티와 그리드 조합

임의의 간격 대신 스케일을 사용하세요

p-3은 패딩 1rem, p-4는 1.5rem, p-5는 3rem을 의미합니다. 이 이름은 픽셀 수가 아니라 스케일 키입니다. 미리보기에서는 p-3 p-md-4를 사용해 768px부터 바깥쪽 패딩을 늘리고, mb-3으로 필드 그룹 사이에 1rem의 간격을 둡니다. 이는 이 예시에서 적용하는 구체적인 방식이지, 새로운 공식 간격 스케일이 아닙니다.

html
<div class="p-3 p-md-4">
  <div class="d-flex flex-wrap gap-2 mb-3">
    <button class="btn btn-primary">Review</button>
    <button class="btn btn-outline-secondary">Reset</button>
  </div>
</div>

코드 참조

지원 사양 읽기

행과 열의 관계를 유지하세요

지원 사양 읽기

Bootstrap 디자인 시스템: 명시적 관계가 있는 필드 구성

레이블, 안내 및 피드백을 연결하세요

form-label은 실제 레이블 요소에 스타일을 적용하며, for 값은 입력 요소의 id와 일치해야 합니다. form-control은 텍스트 입력과 유사한 입력 요소에, form-select는 select 요소에 스타일을 적용합니다. 미리보기에서는 안내 및 오류 ID를 aria-describedby로 연결하고, 실제 제약 조건에는 required를 사용합니다. 클래스 이름만으로 이러한 의미상 관계가 자동 생성되지는 않습니다.

html
<label for="equipment" class="form-label">Equipment</label>
<select id="equipment" class="form-select" required
  aria-describedby="equipment-error">
  <option value="">Choose equipment</option>
  <option>Camera kit A</option>
</select>
<div class="invalid-feedback" id="equipment-error">Choose equipment.</div>

코드 참조

지원 사양 읽기

실제 오류 상태를 사용하고 쉽게 찾아갈 수 있는 요약을 제공하세요

제출 시 예시는 각 필드를 확인하고 is-invalid 및 aria-invalid를 설정한 다음, 오류가 있는 필드로 연결되는 텍스트 링크를 만들고 요약으로 포커스를 이동합니다. 필드 하나를 수정해도 다른 답변은 지우지 않고 해당 필드의 상태만 업데이트합니다. 이 애플리케이션 계층은 필수입니다. Bootstrap 유효성 검사 문서에 따르면 사용자 지정 시각 피드백만으로는 보조 기술에 상태가 완전히 전달되지 않습니다.

  1. 필드를 오류로 표시하기 전에 실제 제약 조건 검사 결과를 확인하세요.
  2. 오류 텍스트를 해당 필드와 연결하고 오류 상태를 명확히 알리세요.
  3. 제출 후에는 유용한 요약이나 첫 번째 오류 필드에 포커스를 두세요.

지원 사양 읽기

Bootstrap 디자인 시스템: 의미를 유지하며 레코드 표시 및 필터링

비교 가능한 데이터에는 표 컴포넌트를 사용하세요

표에는 열 머리글, 행 머리글 및 캡션이 있습니다. table-hover는 호버 스타일을 적용하지만 행을 버튼으로 바꾸지는 않습니다. 필터링하면 일치하는 행의 표시 상태가 바뀌고 aria-live 결과 건수가 업데이트됩니다. 표시되는 상태는 배지 안에 텍스트로도 유지되므로 색상 모드가 바뀌어도 의미를 파악할 수 있습니다.

html
<div class="table-responsive">
  <table class="table table-hover">
    <caption>Fictional equipment reservations</caption>
    <thead><tr><th scope="col">Equipment</th><th scope="col">Status</th></tr></thead>
    <tbody><tr><th scope="row">Camera kit A</th><td>Reserved</td></tr></tbody>
  </table>
</div>

코드 참조

지원 사양 읽기

표 영역 안에서만 가로 스크롤을 적용하세요

table-responsive는 너비가 넓은 표가 화면에 맞지 않을 때 가로 스크롤을 제공합니다. 잘리는 영역 밖으로 나와야 하는 드롭다운을 이 래퍼 안에 넣지 말고, 불가피한 경우에는 동작을 확인하세요. 이 예시에서는 필터를 표 위에 배치합니다. 모바일에서는 데이터 영역만 가로로 스크롤할 수 있어야 하며 페이지 자체는 뷰포트 안에 머물러야 합니다.

지원 사양 읽기

Bootstrap 디자인 시스템: 모달 API로 선택 항목 검토

양식이 유효한 경우에만 여세요

이 인터랙티브 예시는 유효성 검사가 통과한 경우에만 Bootstrap Modal 인스턴스를 만들거나 기존 인스턴스를 재사용해 show를 호출합니다. 이렇게 하면 확인이 필요한 오류를 검토 레이어가 가리지 않습니다. 모달 텍스트는 현재 입력값으로 채워지며, ‘세부 정보 수정’을 선택하면 양식 내용을 유지한 채 모달이 닫힙니다.

자바스크립트
const element = document.getElementById("review-modal");
const modal = bootstrap.Modal.getOrCreateInstance(element);
// Run after validation and after populating the review text.
modal.show();
element.addEventListener("hidden.bs.modal", () => {
  document.querySelector("#reservation button[type=submit]").focus();
});

코드 참조

지원 사양 읽기

모달을 컴포넌트 수명 주기에 따라 다루세요

Bootstrap는 배경 오버레이와 전환 효과를 제어합니다. 표시 상태를 수동으로 전환하면 포커스나 배경 오버레이가 일관되지 않을 수 있으므로, Bootstrap의 메서드와 이벤트를 사용하세요. 이 예시에서는 확인 시 로컬 표에 행을 추가하고 모달을 닫습니다. 예약 서비스는 호출하지 않습니다. 성공 메시지에는 이 로컬 동작만 정확히 안내합니다.

지원 사양 읽기

Bootstrap 디자인 시스템 통합 및 확장: 이 Bootstrap 예제

서로 일치하는 CSS 및 JavaScript 릴리스를 불러오세요

삽입된 예제는 로컬에 저장된 Bootstrap 5.3.8 CSS 및 번들 파일을 불러옵니다. 데이터 속성과 Modal API은 해당 릴리스의 것입니다. Vite 애플리케이션에서는 설정 섹션에 나온 대로 컴파일된 CSS와 필요한 플러그인을 가져오세요. 번들을 불러온 뒤 다른 래퍼를 통해 같은 플러그인을 다시 초기화하지 마세요.

지원 사양 읽기

실제 구성 요소 계약에 따라 확장하세요

  • 예제를 사용해 포커스, 모달 닫기, 테마 변경을 확인하세요.
  • 애플리케이션의 데이터 작업과 Bootstrap 플러그인 동작을 분리하세요.
  • 테마 재정의는 기본, 호버, 포커스, 유효하지 않음, 비활성화 상태에서 다시 확인하세요.

지원 사양 읽기

Bootstrap 디자인 시스템 구성 요소 예제

index.html — 예약 예제 전체

스타일시트, 모달 런타임, 유효성 검사, 필터 및 로컬 확인 기능을 포함한 완전한 Bootstrap 5.3.8 페이지입니다. 이 파일을 index.html로 저장하고 아래 명령어로 폴더를 제공하세요. 고정된 CDN 종속 항목을 사용하려면 네트워크 연결이 필요합니다.

html
<!doctype html><html lang="en" data-bs-theme="light"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Bootstrap equipment reservations — OpenDesign example</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"><style>body{margin:0}main{max-width:1120px;margin:auto}.demo-stat{font-variant-numeric:tabular-nums}.table td,.table th{vertical-align:middle}.table caption{font-size:.875rem}.demo-status:empty{display:none}@media(max-width:575px){.table th,.table td{font-size:.8125rem;padding:.65rem .4rem}.demo-mobile-hide{display:none}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}</style></head><body>
<header class="border-bottom bg-body-tertiary px-3 px-md-4 py-3 d-flex align-items-center justify-content-between gap-3"><div><strong>Studio inventory</strong><span class="badge text-bg-primary ms-2">Bootstrap 5.3.8</span></div><button id="theme" type="button" class="btn btn-outline-secondary btn-sm" aria-pressed="false">Dark mode</button></header>
<main class="p-3 p-md-4"><div class="d-flex align-items-start justify-content-between gap-3 mb-4"><div><p class="text-body-secondary small mb-1">EQUIPMENT / RESERVATIONS</p><h1 class="h3 mb-2">Keep the next shoot ready.</h1><p class="text-body-secondary mb-0">Check equipment, create a local reservation and review its details.</p></div><span class="badge rounded-pill text-primary-emphasis bg-primary-subtle border border-primary-subtle demo-mobile-hide">Interactive example</span></div>
<div class="row g-3 mb-4"><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Equipment</div><strong class="fs-3 demo-stat">12</strong></div></div><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Reservations</div><strong id="count" class="fs-3 demo-stat">3</strong></div></div><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Available</div><strong class="fs-3 demo-stat">8</strong></div></div></div>
<div class="row g-4"><section class="col-lg-7" aria-labelledby="list-title"><div class="d-flex align-items-center justify-content-between gap-3 mb-3"><h2 id="list-title" class="h5 m-0">Reservation list</h2><div><label for="filter" class="visually-hidden">Filter reservations by status</label><select class="form-select form-select-sm" id="filter"><option value="all">All statuses</option><option value="Reserved">Reserved</option><option value="In use">In use</option><option value="Draft">Draft</option></select></div></div><div class="table-responsive border rounded"><table class="table table-hover mb-0"><caption class="px-3">Fictional records. New entries stay in this browser tab.</caption><thead class="table-light"><tr><th scope="col">Equipment</th><th scope="col">Date</th><th scope="col">Status</th></tr></thead><tbody id="rows"><tr data-status="Reserved"><th scope="row" class="fw-medium">Camera kit A<div class="small fw-normal text-body-secondary">Mia Chen</div></th><td>10 Oct</td><td><span class="badge text-primary-emphasis bg-primary-subtle">Reserved</span></td></tr><tr data-status="In use"><th scope="row" class="fw-medium">Lighting studio<div class="small fw-normal text-body-secondary">Alex Kim</div></th><td>10 Oct</td><td><span class="badge text-success-emphasis bg-success-subtle">In use</span></td></tr><tr data-status="Draft"><th scope="row" class="fw-medium">Audio recorder<div class="small fw-normal text-body-secondary">Jules Davis</div></th><td>11 Oct</td><td><span class="badge text-secondary-emphasis bg-secondary-subtle">Draft</span></td></tr></tbody></table></div><p id="empty" class="alert alert-info mt-3" hidden>No reservations match this status.</p><p id="results" class="small text-body-secondary mt-2" aria-live="polite">3 reservations shown</p><div class="alert alert-primary mt-4 mb-0"><strong>Try the system</strong><p class="small mb-0 mt-1">Switch color mode, filter the table, submit an empty form, then review a complete reservation in a Bootstrap modal.</p></div></section>
<section class="col-lg-5" aria-labelledby="form-title"><div class="card"><div class="card-body p-3 p-md-4"><h2 id="form-title" class="h5 mb-3">New reservation</h2><form id="reservation" novalidate><div id="error-summary" class="alert alert-danger" tabindex="-1" role="alert" hidden><strong>Check the reservation details.</strong><ul class="mb-0 mt-2" id="error-links"></ul></div><div class="mb-3"><label class="form-label" for="equipment">Equipment</label><select class="form-select" id="equipment" aria-describedby="equipment-error" required><option value="">Choose equipment</option><option>Camera kit A</option><option>Lighting studio</option><option>Audio recorder</option></select><div id="equipment-error" class="invalid-feedback">Choose equipment for this reservation.</div></div><div class="mb-3"><label class="form-label" for="owner">Reserved by</label><input class="form-control" id="owner" autocomplete="name" aria-describedby="owner-hint owner-error" required><div class="form-text" id="owner-hint">Use a fictional name for this example.</div><div class="invalid-feedback" id="owner-error">Enter the name of the person reserving equipment.</div></div><div class="mb-3"><label class="form-label" for="date">Reservation date</label><input class="form-control" id="date" type="date" aria-describedby="date-error" required><div class="invalid-feedback" id="date-error">Choose a reservation date.</div></div><button type="submit" class="btn btn-primary w-100">Review reservation</button></form><p class="small text-body-secondary mt-3 mb-0">This example validates input locally. It does not reserve real equipment.</p></div></div></section></div><div id="notice" class="alert alert-success mt-4 demo-status" role="status" hidden></div></main>
<div class="modal fade" id="review-modal" tabindex="-1" aria-labelledby="review-title" aria-hidden="true"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="modal-header"><h2 class="modal-title fs-5" id="review-title">Review reservation</h2><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close review"></button></div><div class="modal-body"><dl class="row mb-0"><dt class="col-4">Equipment</dt><dd class="col-8" id="review-equipment"></dd><dt class="col-4">Reserved by</dt><dd class="col-8" id="review-owner"></dd><dt class="col-4">Date</dt><dd class="col-8" id="review-date"></dd></dl><p class="small text-body-secondary mt-3 mb-0">Confirming adds a row to this local example only.</p></div><div class="modal-footer"><button class="btn btn-outline-secondary" data-bs-dismiss="modal" type="button">Edit details</button><button class="btn btn-primary" id="confirm" type="button">Add to example</button></div></div></div></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script><script>
const $=id=>document.getElementById(id);const fields=['equipment','owner','date'];const review=bootstrap.Modal.getOrCreateInstance($('review-modal'));
$('theme').onclick=()=>{const dark=document.documentElement.dataset.bsTheme!=='dark';document.documentElement.dataset.bsTheme=dark?'dark':'light';$('theme').setAttribute('aria-pressed',String(dark));$('theme').textContent=dark?'Light mode':'Dark mode'};
function filter(){let count=0;for(const row of $('rows').rows){row.hidden=$('filter').value!=='all'&&row.dataset.status!==$('filter').value;if(!row.hidden)count++}$('empty').hidden=count>0;$('results').textContent=count+' reservations shown'}$('filter').onchange=filter;
function validateField(id){const el=$(id),invalid=!el.checkValidity();el.classList.toggle('is-invalid',invalid);el.setAttribute('aria-invalid',String(invalid));return !invalid}
$('reservation').onsubmit=e=>{e.preventDefault();const invalid=fields.filter(id=>!validateField(id));$('error-links').replaceChildren();$('error-summary').hidden=invalid.length===0;if(invalid.length){for(const id of invalid){const li=document.createElement('li'),a=document.createElement('a');a.href='#'+id;a.className='alert-link';a.textContent=$(id+'-error').textContent;a.onclick=e=>{e.preventDefault();$(id).focus()};li.append(a);$('error-links').append(li)}$('error-summary').focus();return}for(const id of fields)$('review-'+id).textContent=$(id).value;review.show()};
for(const id of fields)$(id).addEventListener('input',()=>{if($(id).getAttribute('aria-invalid')==='true')validateField(id)});
$('review-modal').addEventListener('hidden.bs.modal',()=>$('reservation').querySelector('button').focus());
$('confirm').onclick=()=>{const row=document.createElement('tr');row.dataset.status='Reserved';const name=document.createElement('th');name.scope='row';name.className='fw-medium';name.textContent=$('equipment').value;const owner=document.createElement('div');owner.className='small fw-normal text-body-secondary';owner.textContent=$('owner').value;name.append(owner);const date=document.createElement('td');date.textContent=$('date').value;const state=document.createElement('td'),badge=document.createElement('span');badge.className='badge text-primary-emphasis bg-primary-subtle';badge.textContent='Reserved';state.append(badge);row.append(name,date,state);$('rows').prepend(row);$('count').textContent=$('rows').rows.length;$('filter').value='all';filter();review.hide();$('notice').hidden=false;$('notice').textContent='Reservation added to this local example. No data was sent.';$('reservation').reset();for(const id of fields){$(id).classList.remove('is-invalid');$(id).removeAttribute('aria-invalid')}};
</script></body></html>

코드 참조

  • 양식 데이터는 어떤 서비스로도 전송되지 않습니다. 예약 확인 정보는 이 페이지 세션에만 존재합니다.
  • 로컬 미리보기에는 동일하게 고정된 CSS 및 JavaScript이 포함되어 있습니다. 이 사본은 해당 파일의 공개 CDN URL을 사용합니다.

필드 레이블, 안내 및 명시적 오류 상태

이 독립형 필드 구성은 Bootstrap 스타일과 실제 유효성 검사 결과를 사용합니다. 페이지 예제에는 세 필드로 이동할 수 있는 링크가 포함된 오류 요약이 추가되어 있습니다. 빨간 테두리만으로는 수정 방법을 전달할 수 없습니다.

html
<form id="reservation" novalidate>
  <label for="owner" class="form-label">Reserved by</label>
  <input id="owner" class="form-control" required
    aria-describedby="owner-hint owner-error">
  <div id="owner-hint" class="form-text">Use a fictional name.</div>
  <div id="owner-error" class="invalid-feedback">Enter a name.</div>
  <button class="btn btn-primary mt-3" type="submit">Review reservation</button>
</form>
<script>
const form = document.querySelector('#reservation');
const input = document.querySelector('#owner');
form.addEventListener('submit', event => {
  event.preventDefault();
  const invalid = !input.checkValidity();
  input.classList.toggle('is-invalid', invalid);
  input.setAttribute('aria-invalid', String(invalid));
  if (invalid) input.focus();
});
</script>

코드 참조

  • .is-invalid는 .was-validated 없이도 명시적으로 설정할 수 있습니다.
  • aria-describedby는 안내 및 오류 텍스트를 연결하고, aria-invalid는 현재 상태를 나타냅니다.
  • 문서에서는 시각적 유효성 검사만 사용자 지정하는 것으로는 보조 기술에 충분한 정보를 제공할 수 없다고 안내합니다.

명확한 레이블을 갖춘 네이티브 검토 모달

이 모달은 Bootstrap의 실제 플러그인, 배경 오버레이, Escape 키 처리 및 포커스 관리를 사용합니다. 제목은 modal-header 안에, 검토 내용은 modal-body 안에, 다음 단계 작업은 modal-footer 안에 배치하세요.

html
<button class="btn btn-primary" data-bs-toggle="modal"
  data-bs-target="#review">Review reservation</button>
<div class="modal fade" id="review" tabindex="-1"
  aria-labelledby="review-title" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h2 class="modal-title fs-5" id="review-title">Review reservation</h2>
        <button class="btn-close" data-bs-dismiss="modal"
          aria-label="Close review"></button>
      </div>
      <div class="modal-body">Camera kit A · 10 October</div>
      <div class="modal-footer">
        <button class="btn btn-outline-secondary" data-bs-dismiss="modal">Edit details</button>
      </div>
    </div>
  </div>
</div>

코드 참조

  • 일치하는 Bootstrap JavaScript 번들을 한 번만 불러오세요.
  • data API는 정적 예제를 엽니다. 작동하는 예약 양식은 입력값이 유효할 때 Modal.getOrCreateInstance를 사용합니다.
  • 열기 전환이 완료될 때까지 기다려야 하는 동작에는 shown.bs.modal을 사용하세요.

반응형 목록 및 양식 구성

lg 중단점에서 장비 목록은 7개 열, 양식은 5개 열을 차지합니다. lg 미만에서는 두 섹션이 세로로 쌓입니다. g-4는 구성 요소 사이에 1.5rem 간격을 둡니다. 열은 너비를 설명하고, 시맨틱 섹션과 제목은 콘텐츠를 설명합니다.

html
<main class="container py-4">
  <div class="row g-4">
    <section class="col-lg-7" aria-labelledby="reservations-title">
      <h2 id="reservations-title" class="h5">Reservations</h2>
      <div class="table-responsive">
        <table class="table table-hover">
          <caption>Fictional equipment reservations</caption>
          <thead><tr><th scope="col">Equipment</th><th scope="col">Status</th></tr></thead>
          <tbody><tr><th scope="row">Camera kit A</th><td>Reserved</td></tr></tbody>
        </table>
      </div>
    </section>
    <section class="col-lg-5" aria-labelledby="new-title">
      <h2 id="new-title" class="h5">New reservation</h2>
    </section>
  </div>
</main>

코드 참조

  • 콘텐츠가 실제로 더 이른 중단점에서 잘 맞는다면 같은 그리드에 col-md-*를 사용할 수 있습니다.
  • CSS 변수를 사용하는 미디어 쿼리 대신 위 중단점 표를 참고하세요. var()는 미디어 쿼리의 임계값으로 사용할 수 없습니다.
04

Bootstrap 디자인 시스템 AI 에이전트 설정

구현 시작점

이 완전한 HTML 예제에는 빌드 단계가 필요하지 않습니다. 파일에 표시된 고정 CDN URL에서 Bootstrap 5.3.8을 가져옵니다. 아래의 간단한 예제에서는 작동하는 이 페이지의 개별 패턴을 따로 살펴봅니다.

sh
# Save the complete index.html from Component Examples in a new folder.
# Serve that folder with Python 3:
python3 -m http.server 8000
# Open http://localhost:8000/ in a browser.

프로젝트를 위한 프롬프트

에이전트 프롬프트
이 가이드와 Bootstrap 5.3.8을 사용해 장비 예약 인터페이스를 구현하세요. row g-4에 col-lg-7과 col-lg-5를 배치하고, p-3 p-md-4 간격, 테마에 대응하는 body 및 subtle/emphasis 색상 역할, 시맨틱 테이블과 레이블이 있는 양식 컨트롤을 사용하세요. Bootstrap의 네이티브 Modal을 열기 전에 명시적 오류와 오류 요약으로 유효성을 검사하세요. 수정 중에는 입력값을 유지하고, 실제 API이 제공되지 않는 한 레코드는 로컬 데모 상태에만 추가하세요. data-bs-theme light/dark와 키보드로 닫기 기능을 지원하세요. 지정된 크기 체계를 임의의 값으로 대체하지 마세요.
05

Bootstrap 디자인 시스템 출처 및 범위

OpenDesign의 Bootstrap 5.3.8 애플리케이션 가이드와 실행 가능한 네이티브 구성 요소 예제입니다. 참고 값은 링크된 Bootstrap 문서와 버전이 고정된 컴파일된 CSS에서 가져왔습니다. 예약 레코드, 레이아웃 구성 및 유효성 검사 요약은 애플리케이션 코드로 직접 작성했으며, 실제 예약은 제출되지 않습니다.