Семантический HTML

Fresh — это современный фреймворк на базе Deno, ориентированный на высокую производительность и минимальное использование JavaScript на клиенте. Основой его подхода является рендеринг на стороне сервера (SSR) с автоматической гидратацией компонентов. В контексте Fresh правильное использование семантического HTML становится критически важным для структуры, доступности и SEO.


Основные принципы семантического HTML

Семантический HTML — это использование тегов в соответствии с их смыслом, а не только для визуального оформления. В Fresh это напрямую влияет на:

  • Доступность: вспомогательные технологии, такие как скринридеры, лучше интерпретируют корректно размеченные страницы.
  • SEO: поисковые системы оценивают семантику страниц при индексации.
  • Поддерживаемость кода: структура страниц становится очевидной даже без визуального рендеринга.

Примеры ключевых семантических элементов:

  • <header> — верхняя часть страницы или секции, содержит логотип, навигацию.
  • <nav> — основной блок навигации.
  • <main> — основное содержимое страницы.
  • <article> — автономный блок контента, например, пост блога.
  • <section> — тематический раздел, объединяющий связанные элементы.
  • <aside> — дополнительная информация или боковая панель.
  • <footer> — нижняя часть страницы или секции с контактами, копирайтом и ссылками.

Семантические теги в компонентах Fresh

В Fresh компоненты создаются как функции, возвращающие JSX. При этом использование семантических тегов в JSX идентично стандартному HTML:

export default function BlogPost(props: { title: string; content: string }) {
  return (
    <article>
      <header>
        <h1>{props.title}</h1>
      </header>
      <section>
        <p>{props.content}</p>
      </section>
      <footer>
        <p>Опубликовано: {new Date().toLocaleDateString()}</p>
      </footer>
    </article>
  );
}

Ключевые моменты:

  • <article> оборачивает автономный контент, который может быть повторно использован или отдельно индексирован.
  • <header> и <footer> внутри <article> содержат информацию, специфичную для этой записи.
  • <section> делит контент на логические блоки без потери семантики.

Доступность и ARIA в Fresh

Семантический HTML усиливается использованием ARIA-атрибутов для динамического контента:

<button aria-expanded="false" aria-controls="menu" id="menu-button">
  Меню
</button>
<nav id="menu" hidden>
  <ul>
    <li><a href="/about">О нас</a></li>
    <li><a href="/contact">Контакты</a></li>
  </ul>
</nav>
  • aria-expanded показывает состояние раскрывающегося элемента.
  • aria-controls связывает кнопку с навигационной панелью.
  • Атрибут hidden скрывает элемент от визуального рендеринга, но семантика сохраняется.

Fresh поддерживает SSR, поэтому ARIA-атрибуты применяются на сервере, что делает интерфейсы доступными даже до гидратации на клиенте.


Структурирование страниц с использованием семантики

Корректная структура страницы в Fresh обычно выглядит так:

export default function Page() {
  return (
    <html lang="ru">
      <head>
        <title>Пример страницы</title>
      </head>
      <body>
        <header>
          <h1>Заголовок сайта</h1>
          <nav>
            <ul>
              <li><a href="/">Главная</a></li>
              <li><a href="/blog">Блог</a></li>
            </ul>
          </nav>
        </header>
        <main>
          <section>
            <h2>Раздел контента</h2>
            <p>Текст раздела с подробным описанием темы.</p>
          </section>
          <aside>
            <h3>Сайдбар</h3>
            <p>Дополнительная информация или ссылки.</p>
          </aside>
        </main>
        <footer>
          <p>© 2025 Компания Fresh</p>
        </footer>
      </body>
    </html>
  );
}

Особенности:

  • <main> присутствует только один раз на странице.
  • <aside> используется для второстепенного контента.
  • Каждая секция имеет свой заголовок, что улучшает навигацию и SEO.

Комбинирование семантики с динамическими компонентами

Fresh позволяет создавать интерактивные элементы без потери семантики:

import { useState } from "preact/hooks";

export default function FAQItem(props: { question: string; answer: string }) {
  const [open, setOpen] = useState(false);

  return (
    <section>
      <button
        aria-expanded={open}
        onCl ick={() => setOpen(!open)}
      >
        {props.question}
      </button>
      {open && <p>{props.answer}</p>}
    </section>
  );
}
  • Использование <section> вокруг вопроса и ответа сохраняет логическую структуру.
  • <button> с aria-expanded делает компонент доступным.
  • Динамическая отрисовка не ломает семантическую разметку.

Рекомендации по семантике в Fresh

  • Все страницы должны иметь один <main> и корректно вложенные <header> и <footer>.
  • Разделы контента должны использовать <section> или <article>, а не <div> без смысла.
  • В интерактивных компонентах применять ARIA-атрибуты для сохранения доступности.
  • Навигация должна использовать <nav>, а не произвольные списки <div>.

Соблюдение этих принципов обеспечивает корректную работу SSR, улучшает SEO и делает интерфейсы доступными для всех пользователей.