Создайте ответ на опрос, в котором варианты не противоречат друг другу: встроенные флажки ONS, взаимоисключающие ответы, точные ссылки на типографику и цвета, а также полный локальный сценарий проверки.
Нативные компоненты ONS 73.13.1 Checkbox и Mutually Exclusive CSS/JavaScript. Оригинальный вопрос, проверка и просмотр ответов в приложении, явная подстановка Arial. · Справочник по реализации
02
Дизайн-система ONS Справочник по дизайну
ONS Design System 73.13.1 скомпилирован: CSS, JavaScript и переменные Sass проверены по общедоступному руководству по стилю. В примере используются нативные компоненты Checkbox и Mutually Exclusive. В отдельном примере вместо OpenSans используется Arial; в инструкции по сборке для production предусмотрено копирование упакованных шрифтов. Вопрос о поездке и локальная проверка — оригинальный демонстрационный контент.
ONS занимается как сбором статистических данных, так и публикацией информационных материалов. В анкете взаимоисключающие ответы важны для качества данных: пользователь не должен одновременно указать способ передвижения и сообщить, что поездки не было. Нативный компонент Mutually Exclusive связывает эти варианты и с помощью пояснения помогает пользователям вспомогательных технологий понять, почему выбор снимается.
В примере задан оригинальный вопрос о поездке в библиотеку и предусмотрен локальный просмотр ответа. Здесь намеренно не используются фирменные изображения ONS и не утверждается, что ответы собираются. Для реального опроса потребуются собственные правила согласия, хранения данных, маршрутизации и серверной проверки.
Основной шрифт — Open Sans со стилистическим набором 1, выбранным за характерные формы букв. В нативной таблице типографики Sass заданы фиксированные малые и крупные значения, а не придуманная непрерывная шкала. Для основного текста используются размер 18px и интерлиньяж 28px. Основной крупный класс на среднем брейкпоинте меняется с 32/44 на 48/56.
На странице с одним вопросом заголовок h 1 можно поместить в легенду fieldset, чтобы доступное имя группы совпадало с видимым заголовком. Не добавляйте перед ним второй несвязанный h 1. В примере контекст сервиса вынесен в абзац меньшего размера, а инструкция по выбору расположена под легендой.
В автономной демонстрации явно используется Arial, поэтому отсутствуют запросы к недоступным шрифтам. В инструкции по установке шрифты копируются вместе с CSS; это необходимо, если вместо резервного шрифта должен использоваться опубликованный OpenSans.
ONS назначает семантические переменные базовым цветам. Для текста используется чёрный, для обычных ссылок — океанический синий, для основной кнопки — листовой зелёный. Цвет фокуса — солнечный жёлтый. Рубиновый красный обозначает ошибку, но сообщение об ошибке всё равно должно объяснять, что нужно сделать. Зелёная кнопка «Продолжить» не означает, что ответ уже прошёл проверку.
В локальной анкете используются нативная рамка и оформление выбранного состояния флажка. Ответы не оформлены каждый в виде отдельной маркетинговой карточки. Короткая нейтральная линия сверху отделяет самостоятельный пример от вопроса, не копируя шапку ONS.
Сохраните видимое нативное оформление фокуса и на флажке, и на кнопке действия.
Перед обычными вариантами разместите инструкцию «Выберите все подходящие варианты».
Отделите противоположный ответ словом «Или», чтобы различие было понятно ещё до взаимодействия.
Ширина в двенадцатиколоночной сетке задаётся классами, например ons-col-8@m. При ширине 740px и выше такой класс занимает восемь колонок; ниже этого значения тот же элемент заполняет всю доступную ширину контента. В локальном примере используется эта нативная колонка: длинный вопрос переносится в удобном для чтения формате, а не растягивается на весь экран.
В проверенном релизе максимальная ширина стандартного контейнера составляет 64.6256rem, а горизонтальный внутренний отступ — 1rem. В общедоступном руководстве по сетке также указана базовая сетка 8px и промежутки 16/24px при границе интервалов 600px. Не смешивайте эти положения со средним брейкпоинтом колонки 740px: это не единый универсальный порог для мобильных устройств.
При просмотре ответов вопрос заменяется в той же колонке, а кнопка «Изменить ответы» возвращает пользователя к имеющимся элементам управления. Значения остаются в памяти; перехода по маршруту и сетевого запроса нет.
Доступные утилиты интервалов подробнее, чем указано в описании базовой сетки 8px: нижние отступы xs, s, m, l и xl при корневом размере 16px составляют 12,16,20,24 и 32px. Поэтому в справочнике фактические значения утилит приведены отдельно от рекомендаций по сетке.
Для флажка внутри ons-checkbox используются ons-checkbox__input и связанный с ним ons-checkbox__label. У поля сохраняются обычные атрибуты name и value, поэтому стандартная семантика формы продолжает работать. Более общая структура ons-checkboxes__item обеспечивает отступы и область нажатия, предусмотренные таблицей стилей.
Для обычных вариантов используется общий класс ons-js-exclusive-group-item. Для последнего варианта вместо него применяется ons-js-exclusive-option с атрибутом data-deselect-message, поясняющим эффект выбора. Элемент span для области динамических объявлений должен присутствовать с обоими атрибутами-прилагательными: это не просто декоративная разметка. Его удаление нарушит предположения нативного контроллера.
Этот исходный пример полностью описывает три обычных варианта и один противоположный ответ. Адаптируйте существительные и значения к реальному вопросу; не ограничивайтесь тем, что переименуете несвязанный элемент управления проверкой в «взаимоисключающий».
html
<fieldset class="ons-fieldset"><legend class="ons-fieldset__legend"><h1 class="ons-fieldset__legend-title">How did you travel to your local library last week?</h1></legend>
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<p class="ons-checkboxes__label">Select all that apply</p><div class="ons-checkboxes__items"><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="walk" name="travel" value="walk" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="walk" id="walk-label">Walk or wheel</label></span></span><br><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="cycle" name="travel" value="cycle" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="cycle" id="cycle-label">Cycle</label></span></span><br><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="bus" name="travel" value="bus" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="bus" id="bus-label">Bus or tram</label></span></span><br></div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s"><span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span><span class="ons-checkbox"><input type="checkbox" id="none" name="travel" value="none" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" data-deselect-message="Selecting this will uncheck all other options"><label class="ons-checkbox__label" for="none" id="none-label"><span class="ons-u-vh">Or, </span>I did not visit the library</label></span></p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="deselected" data-option-adjective="deselected"></span></div></fieldset>
Дизайн-система ONS Проверка и поведение при изменении
Состояние библиотеки и состояние приложения
Библиотека отвечает за снятие отметок с противоположных вариантов. Небольшой обработчик приложения в примере лишь проверяет, выбран ли хотя бы один ответ, прежде чем отобразить локальный экран проверки. Если ничего не выбрано, он показывает текст ошибки и переводит фокус на связанное сообщение. Ссылка из ошибки ведёт прямо к первому варианту, где пользователь может выполнить действие.
Помимо значения флажка в DOM, контроллер отслеживает кэшированное состояние hasValue. Если сбросить флажок только с помощью checked=false, кэш может остаться устаревшим. Поэтому действие сброса нажимает каждый отмеченный элемент, позволяя нативным обработчикам обновить модель, а затем возвращает фокус к вопросу. Это конкретный аспект интеграции, который нельзя проверить, просто посмотрев на таблицу стилей.
На экране проверки выбранные варианты представлены списком подписей. Действие «Изменить ответы» сохраняет элементы управления и их выбранное состояние. Экран не утверждает, что ответ на опрос получен: за этим образцом не стоит сервер.
Дизайн-система ONS Подключение ресурсов и шаблонов
Два поддерживаемых способа
В npm-пакет входят скомпилированные ресурсы, исходники Sass, макросы Nunjucks и базовый шаблон страницы. В этом примере используется способ с готовыми ресурсами HTML: скопируйте официальные CSS и main.js, воспроизведите документированную разметку, а затем загрузите скрипт после содержимого body. Когда DOM будет готов, скрипт инициализирует соответствующие хуки компонентов.
В проекте с серверным рендерингом вместо этого можно использовать файлы макросов Nunjucks из каталога components. Макрос Checkbox принимает массив флажков, подписи, описания, параметры ошибок и настройки mutuallyExclusive. Если задать dontWrap, ответственность за fieldset переходит к внешнему компоненту вопроса; это не способ отказаться от доступного названия группы.
При выборе отдельных файлов Sass сначала импортируйте системные переменные, вспомогательные функции, утилиты, базовые стили и объекты, затем правила компонентов и все их зависимости. Полный скомпилированный CSS позволяет не подбирать зависимости для этого небольшого автономного примера.
Зафиксируйте версию пакета и размещайте css, скрипты и шрифты в одном стабильном локальном каталоге ресурсов.
Для статической страницы используйте скомпилированный HTML, а для приложения с серверным рендерингом настройте пути к макросам Nunjucks.
Используйте CSS, JavaScript и разметку из одного релиза; после обновления повторно проверьте взаимоисключение.
Дизайн-система ONS Проверьте противоречивые ответы
Проверьте смысл данных
Выберите «Пешком» и «Автобус», затем выберите «Я не посещал библиотеку». Оба предыдущих варианта должны сняться. Затем выберите «Велосипед»: противоположный ответ должен сняться, а отметка у «Велосипед» — сохраниться. Повторите действия клавишей Space на элементах в фокусе и проверьте область объявлений, а не полагайтесь только на визуальную отметку.
Продолжите без выбора, чтобы проверить ошибку, затем проверьте корректный ответ и вернитесь с помощью действия «Изменить ответы». В завершение выполните сброс после последовательности противоречивых ответов и выберите другой вариант: так можно обнаружить устаревшее состояние нативного контроллера. При ширине экрана 390px вопрос и все подписи должны оставаться читаемыми без горизонтальной прокрутки страницы.
Эти тесты проверяют локальное взаимодействие, но не отправку данных в производственный опрос, сертификацию доступности или статистическое качество вопроса. Для реального сервиса по-прежнему нужна серверная проверка противоречивых значений и исследование того, все ли категории ответов предусмотрены.
Полный документ включает разметку, элементы управления и инициализацию. Распакуйте связанный архив примера, чтобы получить нужные относительные пути к ресурсам поставщика, затем запустите его через HTTP-сервер.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>ONS survey question specimen</title><link rel="stylesheet" href="vendor/ons-73.13.1/css/main.css"><style>body,input,button,select,textarea{font-family:Arial,sans-serif!important}body{margin:0}main{padding-top:32px;padding-bottom:32px}.specimen{border-top:4px solid var(--ons-color-ocean-blue);padding-top:16px}.actions{display:flex;gap:24px;align-items:center;flex-wrap:wrap;margin-top:32px}[hidden]{display:none!important}.error{border-left:4px solid var(--ons-color-errors);padding:16px;margin:24px 0;color:var(--ons-color-errors)}.quiet{color:var(--ons-color-text-light)}fieldset{min-width:0}.ons-checkbox__label{max-width:100%}</style><main class="ons-container"><p class="ons-u-fs-s specimen">Independent specimen · Original library survey</p><div class="ons-grid"><div class="ons-grid__col ons-col-8@m"><section id="question"><p class="quiet">Travel · Question 1 of 1</p><div id="error" class="error" tabindex="-1" hidden><strong>Select a travel method or tell us you did not visit.</strong><p><a href="#walk">Go to the answer choices</a></p></div><form id="survey" novalidate><fieldset class="ons-fieldset"><legend class="ons-fieldset__legend"><h1 class="ons-fieldset__legend-title">How did you travel to your local library last week?</h1></legend>
<div class="ons-js-mutually-exclusive ons-mutually-exclusive">
<p class="ons-checkboxes__label">Select all that apply</p><div class="ons-checkboxes__items"><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="walk" name="travel" value="walk" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="walk" id="walk-label">Walk or wheel</label></span></span><br><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="cycle" name="travel" value="cycle" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="cycle" id="cycle-label">Cycle</label></span></span><br><span class="ons-checkboxes__item"><span class="ons-checkbox"><input type="checkbox" id="bus" name="travel" value="bus" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-group-item"><label class="ons-checkbox__label" for="bus" id="bus-label">Bus or tram</label></span></span><br></div>
<p class="ons-checkboxes--mutually-exclusive__item ons-u-mt-s"><span class="ons-checkboxes__label ons-u-fs-r--b" aria-hidden="true">Or</span><span class="ons-checkbox"><input type="checkbox" id="none" name="travel" value="none" class="ons-checkbox__input ons-js-checkbox ons-js-exclusive-option" data-deselect-message="Selecting this will uncheck all other options"><label class="ons-checkbox__label" for="none" id="none-label"><span class="ons-u-vh">Or, </span>I did not visit the library</label></span></p>
<span class="ons-js-exclusive-alert ons-u-vh" role="alert" aria-live="polite" data-group-adjective="deselected" data-option-adjective="deselected"></span></div></fieldset><div class="actions"><button class="ons-btn" type="submit"><span class="ons-btn__inner">Review answer</span></button><button id="reset" type="button" class="ons-btn ons-btn--secondary"><span class="ons-btn__inner">Reset</span></button></div></form><p class="ons-u-mt-l ons-u-fs-s quiet">Practice only. Your selection stays in this page and is not submitted.</p></section><section id="review" hidden><h1 tabindex="-1">Review your answer</h1><h2 class="ons-u-fs-m">Travel to the library last week</h2><ul id="answer"></ul><p>No response has been sent. Return to the question to change your selection.</p><button id="change" class="ons-btn ons-btn--secondary"><span class="ons-btn__inner">Change answers</span></button></section></div></div></main><script src="vendor/ons-73.13.1/scripts/main.js"></script><script>const form=document.querySelector('#survey'),q=document.querySelector('#question'),r=document.querySelector('#review'),err=document.querySelector('#error'),checks=[...form.querySelectorAll('input[type=checkbox]')];form.onsubmit=e=>{e.preventDefault();const chosen=checks.filter(x=>x.checked);if(!chosen.length){err.hidden=false;err.focus();return}err.hidden=true;document.querySelector('#answer').replaceChildren(...chosen.map(x=>{let li=document.createElement('li');li.textContent=document.querySelector('label[for="'+x.id+'"]').textContent.replace(/^Or, /,'');return li}));q.hidden=true;r.hidden=false;r.querySelector('h1').focus()};document.querySelector('#change').onclick=()=>{r.hidden=true;q.hidden=false;checks[0].focus()};document.querySelector('#reset').onclick=()=>{checks.filter(x=>x.checked).forEach(x=>x.click());err.hidden=true;checks[0].focus()};window.demoReady=true;</script></html>
Скачайте полный пример из раздела «Источники». Точная команда локального запуска приведена в README.
Оставьте пути к ресурсам поставщика относительными к этому документу; архив включает все ресурсы, используемые в предварительном просмотре.
04
Дизайн-система ONS Настройка агента
Отправная точка для реализации
В локальном примере используются скомпилированные CSS и JavaScript Native 73.13.1. Arial — явно заданный локальный резервный шрифт; в инструкциях для производственной среды указаны входящие в пакет шрифты OpenSans. Полный ZIP-архив рабочего примера в разделе Sources также содержит точные зависимости для предпросмотра и полный документ. Распакуйте его, выполните в этой директории python3 -m http.server 8080, затем откройте http://localhost:8080/ons.html. Не открывайте примеры с модулями через file://.
bash / html
npm install --save-exact @ons/[email protected]
mkdir -p public/vendor/ons
cp -R node_modules/@ons/design-system/css public/vendor/ons/
cp -R node_modules/@ons/design-system/scripts public/vendor/ons/
cp -R node_modules/@ons/design-system/fonts public/vendor/ons/
<!-- In your page head -->
<link rel="stylesheet" href="/vendor/ons/css/main.css">
<!-- Place the compiled component markup in the body. -->
<!-- Immediately before </body>; initializes matching component hooks -->
<script src="/vendor/ons/scripts/main.js"></script>
Запрос для вашего проекта
Промпт для AI-агента
Создайте независимый образец опроса на ONS73.13.1, используя нативные хуки Checkbox и Mutually Exclusive, связанные fieldset/legend, группу обычных вариантов ответа и один противоположный ответ. Добавьте обязательную область динамических объявлений и атрибуты снятия отметки. Подключите соответствующие нативные CSS и main.js; не создавайте собственный контроллер взаимоисключения. Добавьте локальную проверку пустого ответа и просмотр ответа с сохранением изменений, не заявляя о получении данных сервером. Выполняйте сброс через нативные события, чтобы состояние кэша оставалось согласованным. Используйте ons-col-8@m и проверенные правила типографики и семантических цветов, не добавляя официальные элементы фирменного стиля.
05
Дизайн-система ONS Источники и область применения
Независимый пример реализации с оригинальным текстом опроса. Нативный код лицензирован по MIT; лицензирование айдентики и содержимого ONS регулируется отдельно. Ответы не передаются, не сохраняются и не представляются как официальная статистика.