Skip to content

HTML — Элементы ​

💻 dialog — нативная модалка ​

html
<dialog id="modal">
	<h2>Заголовок</h2>
	<p>Содержимое</p>
	<button autofocus>Закрыть</button>
</dialog>

<button onclick="modal.showModal()">Открыть</button>
js
const modal = document.querySelector("#modal");

// Открыть как модалку (с backdrop, блокирует фон)
modal.showModal();

// Открыть как обычный диалог (без блокировки)
modal.show();

// Закрыть
modal.close();
modal.close("result"); // с возвращаемым значением

// Закрытие по Escape — встроено автоматически
// Закрытие по кнопке
document.querySelector("button").addEventListener("click", () => modal.close());

// Получить результат
modal.addEventListener("close", () => {
	console.log(modal.returnValue); // значение из close('result')
});
css
/* Стилизация */
dialog {
	border: none;
	border-radius: 12px;
	padding: 2rem;
	box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
	max-width: min(560px, 90vw);
}

/* Фон */
dialog::backdrop {
	background: oklch(0 0 0 / 0.5);
	backdrop-filter: blur(4px);
}

/* Анимация появления */
dialog[open] {
	animation: dialog-in 0.2s ease;
}

@keyframes dialog-in {
	from {
		opacity: 0;
		transform: scale(0.95);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

Встроенная функциональность:

  • Закрытие по Escape
  • Фокус-ловушка (Tab не уходит за пределы)
  • ::backdrop — фон
  • ARIA роль dialog автоматически
  • autofocus — первый фокус на нужном элементе

💻 meter — gauge-индикатор ​

Индикатор значения в известном диапазоне (заряд, оценка, использование):

html
<!-- min, max, value — обязательные -->
<meter min="0" max="100" value="75">75%</meter>

<!-- low, high, optimum — задают "хорошую" зону -->
<meter min="0" max="100" low="30" high="70" optimum="100" value="85">85%</meter>

<!-- Примеры -->
<p>Заряд: <meter min="0" max="1" value="0.8">80%</meter></p>
<p>Рейтинг: <meter min="0" max="5" value="4.2" title="4.2 из 5"></meter></p>
<p>Хранилище: <meter min="0" max="50" value="47" high="40">47 GB</meter></p>

Браузер автоматически меняет цвет:

  • Зелёный — значение в зоне optimum
  • Жёлтый — значение в субоптимальной зоне (low..high)
  • Красный — значение в опасной зоне
css
/* Стилизация через ::-webkit-meter-* (ограниченная) */
meter {
	width: 200px;
	height: 12px;
}

/* Сброс и кастомный стиль */
meter {
	-webkit-appearance: none;
	appearance: none;
	background: #e5e7eb;
	border-radius: 999px;
	overflow: hidden;
}

meter::-webkit-meter-bar {
	background: transparent;
}
meter::-webkit-meter-optimum-value {
	background: #22c55e;
}
meter::-webkit-meter-suboptimum-value {
	background: #f59e0b;
}
meter::-webkit-meter-even-less-good-value {
	background: #ef4444;
}

💻 output — результат вычислений ​

Семантический элемент для вывода результата формы:

html
<form oninput="result.value = Number(a.value) + Number(b.value)">
	<input type="number" id="a" value="0" /> + <input type="number" id="b" value="0" /> =
	<output name="result" for="a b">0</output>
</form>
html
<!-- Калькулятор -->
<form id="calc">
	<label>Цена: <input type="number" id="price" value="1000" /></label>
	<label>Кол-во: <input type="number" id="qty" value="1" /></label>
	<output id="total" for="price qty">1000 $</output>
</form>

<script>
	const form = document.querySelector("#calc");
	form.addEventListener("input", () => {
		const price = +form.querySelector("#price").value;
		const qty = +form.querySelector("#qty").value;
		form.querySelector("#total").value = `${(price * qty).toLocaleString()} $`;
	});
</script>

Зачем вместо <span>:

  • Семантически означает "вычисленный результат"
  • Атрибут for связывает с источниками данных
  • Screen reader объявляет при изменении (live region)

⚠️ Подводные камни ​

  • dialog.showModal() — фокус-ловушка работает только при открытии через JS, не через open атрибут
  • dialog закрывается по Escape — добавь form method="dialog" внутри чтобы кнопки тоже закрывали
  • <meter> — не использовать для прогресса процессов, для этого <progress>
  • <meter> стилизация — сильно ограничена, разная в Chrome и Firefox
  • <output> — не сохраняется при сабмите формы (не является form control)

Built with VitePress and ❤️