Привет! Я Толя, Frontend-разработчик в Selectel. В мире фронтенда есть «острый недостаток» фреймворков, поэтому я, как и 90% JavaScript-разработчиков, решил разработать собственный. В тексте расскажу, как «запихать» HTML-элементы в CSS и не испортить проект. Читайте до конца — вас ждет неожиданный сюжетный поворот.

Используйте навигацию, если не хотите читать текст полностью:

О проекте
Работа с элементами
Заключение

О проекте


Принцип DRY


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

Чтобы предотвратить ошибку, я решил придерживаться главной заповеди чистого кода — DRY, Don’t Repeat Yourself. Принцип помогает сократить повторяющийся код за счет разделения проекта на мелкие независимые модули. Туда можно с легкостью вносить новые изменения — другие блоки не пострадают.


DRY замотивировал меня разработать такой проект, в котором принцип осуществлялся на 110%. Изначально, чтобы сверстать страницу, нужно было описать структуру документа в HTML, а потом — в селекторах на CSS. Приходилось проделывать работу дважды.

Стало интересно, что будет, если поменять структуру документа. Перестать тратить время на написание кода в двух местах и сконцентрироваться только на CSS? В своем фреймворке я оптимизировал структуру и сделал ее намного удобнее (вот только для кого?).

Работа с фреймворком


Кратко расскажу о принципе работы фреймворка. HTML in CSS — это способ избежать повторяющийся код. В нем можно писать только на CSS, HTML будет генерироваться самостоятельно.

Перед вами стандартная страница с версткой:

<head>
    <style>
	h1#title {
		font-size: x-large;
                margin-bottom: 32px;
        }

        main#main {
	        color: purple;
        }
    </style>
</head>
<body>
    <h1 id=”title”>Заголовок</h1>

    <main id=”main”>
	Крутой контент
    </main>
</body>


Синьоры и сеньориты среди вас, вероятно, заметили, что лишняя информация находится:
  • в HTML — h1 id=”title”;
  • в CSS — h1#title {;
  • в HTML — main id=”main;
  • в CSS — main#main.

HTML полностью повторяет код в CSS, поэтому я решил убрать тег . Без него мы не потеряем ничего, кроме контента:

<head>
    <style>
	h1#title {
	  font-size: x-large;
          margin-bottom: 32px;
        }

        #title:before {
          content: “Заголовок”;
        }

        main#main {
            color: purple;
        }

        #main:before {
            content: “Крутой контент”;
        }
    </style>
</head>
<body></body>

Как вы догадались, получился не принцип DRY, а скорее — RY, Repeat Yourself. В исправлении этого и заключается идея HTML in CSS!

Особенности фреймворка


HTML in CSS можно использовать практически на любом коде сайта, но есть несколько оговорок.

  • Селекторы могут создать только один элемент и не более — двух одинаковых id не бывает.

#parent > #child {}

  • Текстовое содержание должно находиться в псевдоэлементах, иначе не получится передать внутреннее содержимое тега через CSS.

#selectel-link::before {
    content: “Ссылка на наш сайт”;
}

  • Страница может запускаться только в рантайме, поэтому о SEO-оптимизации стоит забыть. Это норма для многих современных фреймворков, если не говорить об их SSR-вариациях.



Работа с элементами


О проекте и его особенностях мы узнали. Теперь рассмотрим, как использовать ссылки, вложенность, порядок и другие функции с помощью инструмента.

В фреймворке есть «козырь в рукаве» — это селекторы атрибутов. Он предлагает широкий выбор элементов для разработки: от картинок и видео до айфреймов. Мы часто будем использовать его в наших примерах.

Ссылки


Задача: Разместить ссылку на страницу с сайтом Selectel, которая будет выглядеть так:

<a id=”selectel-link” href=”selectel.ru”></a>

Решение: Пишем стили с атрибутом href, чтобы добавить ссылку на сайт.

a#selectel-link[href=”selectel.ru”] {
  display: block;
}

#selectel-link::before {
  content: “Ссылка на наш сайт”;
}

А если хотите, чтобы ссылка открывалась в новой вкладке?

<a id=”selectel-link” href=”selectel.ru” target=”_blank”></a>

Решение: Пишем стили с атрибутом target.

a#selectel-link[href=”selectel.ru”][target=”_blank”] {
  display: block;
}


В результате мы сгенерировали:

<a id=”selectel-link” href=”selectel.ru” target=”_blank”></a>

Вложенность


Задача: поместить один HTML-элемент внутрь другого.

Решение: Создаем селектор дочерних элементов, чтобы добавить один элемент в другой.

#parent {
  width: 200px;
  height: 200px;
  background-color: blue;
}

#parent > #child {
  width: 100px;
  height: 100px;
  background-color: green;
}

Генерируем HTML:

<div id=”parent”>
  <div id=”child”></div>
</div>


Порядок


Задача: расположить несколько элементов внутри родителя в определенном порядке.

Решение: Используем селекторы псевдоклассов :nth-child, :first-child, :last-child, чтобы определить порядок элементов.

#parent > #foo:last-child {
  font-size: 10px;
}

#foo::before {
  content: “Я последний”;
}

#parent > #bar:first-child {
  font-size: 20px;
}

#bar::before {
content: “А я первый”;
}

Генерируем HTML:

<div id=”parent”>
  <div id=”bar”></div>
  <div id=”foo”></div>
</div>


JavaScript


К сожалению, фреймворк не поддерживает JavaScript, но это не мешает подключить к нему внешний файл — main.js. Да и никто не запретит нам описывать селекторы для тегов script и добавлять туда атрибуты.

script#my-script[src="/main.js"] {}

В main.js можно использовать любой интерактив, который нужен сайту, — например, обработку событий, клиентский роутер и другие.

Заключение


Возможно, некоторые уже захотели переписать свой продакшн-сайт на HTML in CSS, но мне жаль вас огорчать — на самом деле это фреймворк-шутка.

Одним вечером мне стало интересно, как парсится CSS и как выглядит его структура. В процессе изучения пришла в голову идея создать свой фреймворк. Как говорится, закрепил теорию практикой. Кстати, фреймворк занимает около 120 строк неубористого кода. Если интересно, можете посмотреть на GitHub.


А какие фреймворки вы разрабатывали? Расскажите о них в комментариях. Возможно, они пригодятся нашим читателям.

Комментарии (9)


  1. vhlv
    01.08.2024 09:45
    +17

    #container > .box:not(:last-child) ~ .box > .innerBox:nth-of-type(odd):not(.highlight)

    Потом сидишь и смотришь на нечто подобное и пытаешься разобраться, что же хотел изобразить ты или твой коллега


  1. isumix
    01.08.2024 09:45

    Интересная задумка!
    Вообще CSS сделан чтобы с помошью селекторов и "немножно" стилей, застилизовать большое количество HTML. CSS обычно статичен, HTML обычно генерируется.
    Как вы предлагаете сгенерить например динамический список каточек с данными из одного описания CSS?
    ПС: сам разрабытываю альтернативу React :)


  1. ImagineTables
    01.08.2024 09:45
    +1

    Я разработал фреймворк «а-АПчхИ!» (от alert-API, a-API) для мобильных приложений с UI на базе HTML. Дело в том, что onAlert — единственное событие WebView, которое позволяло передавать данные из скрипта в нативный код, без СМС и регистрации собственного веб-сервера. Фреймворк запаковывал вызов и все аргументы в строку, делал alert(), а на той стороне строку разбирал специальный парсер и совершал нативный Invoke со всеми параметрами.

    Кстати, это не шутка. Как по мне, на клоунов больше похожи те, кто тащит веб-сервер чисто для того, чтобы маршрутизировать запросы в вызовы функций. (Это и усложняет код, и нагружает телефон).

    Долгие годы я пользовался а-АПчхИ!, пока не нашёл решение ещё лучше, и теперь делюсь предыдущим решением с миром. Уж не жалко. Уж пользуйтесь.


    1. Opaspap
      01.08.2024 09:45

      я однажды видел реализацию межпроцессного общения на помните такой в 98й винде был нативный мессенджер, так вот на его протоколе, меня каким то чудом попросили разобраться почем та штука не работает, серьезная организация, так вот не работала она потому, что они развернули домен (уже 200е годы, может даже 5й) а домен этот мессенджер запрещает как устаревший несекурный итд. Ну и в итоге она просто в домене не работала, так как это какой то узел выделили его в отдельную физ сеть несекурную и крутили на нем че там должно было крутиться.
      (А я так понял те ребята, что такое сотворили презирали tcp чтоли, что то в таком духе. )
      Ах я про что - в наше время, лучше использовать те способы коммуникации которые рекомендует вендор, это сильно уменьшит вероятность того, что с очередным релизом вся ваша велосипедная фабрика застрянет и вам вместо того чтобы на пенсии на багамах сидеть, придется ее чинить.


  1. Opaspap
    01.08.2024 09:45
    +1

    #parent

    вот тут остались повторы, скрестите с less, stylus или что там нынче в моде :)


    1. akopyl Автор
      01.08.2024 09:45

      Да, это логическое продолжение этого проекта, идея мне очень нравится!

      Тут и циклы появятся, и переменные, правда ограниченные билд таймом…

      Но если к всему этому прикрутить SSR, и компилировать препроцессор CSS на сервере, то это заиграет новыми красками. Там и SEO будет


  1. Andrey098
    01.08.2024 09:45

    Интересный подход, спасибо за статью!


  1. Format-X22
    01.08.2024 09:45

    Я 10 лет назад чисто на JS писал фронтенд - и HTML и CSS и JS логику - всё на JS. И выглядело всё как объекты ключ-значение, вложенные друг в друга, массивы и прочее. И были у меня и классы до появления в JS классов, и флексбоксы до изобретения флекса в CSS и под мобилой выглядело как нативное приложение. И под десктоп компилилось до изобретения электрона. И UI компонентов на каждый чих, включая люто функциональные гриды и всякие генераторы графиков. И работало даже на IE 6, включая флексбоксы, да.

    Но кто будет платить 5к баксов в год за лицензию? Верно, никто. И оно умерло. Спи спокойно, ExtJS, ты был легендой. Но неумелая монетизация убивает любой проект.


  1. dmitryvolochaev
    01.08.2024 09:45

    на самом деле это фреймворк-шутка

    В каждой шутке есть доля шутки