Томас Димнет написал статью под названием «Взлёт и падение Bootstrap», в которой он пытается впарить Failwind, как если бы он каким-то волшебным образом был лучше, чем bootcrap. Глупая и невежественная статья. И так вышло, что мой ответ на эту статью оказался настолько длинным, что я решил оформить его в отдельный материал.
Как обычно, я не подразумеваю под словами «невежество» и «невежда» какие-то страшные оскорбления. Таким образом я обозначаю людей, которым не известны наилучшие практики. Проблема в том, что фреймворки сами по себе накачаны таким огромным количеством глупостей, что написать статью совсем без ругательств и нападок попросту невозможно.
Мне лень качественно аргументировать и документировать свое отвращение к фреймворкам, и в обычной ситуации я бы не стал акцентировать внимание на этой дурацкой статье. Но меня здорово взбесили приведенные в ней бестолковые примеры. Они бесстыдно демонстрировали, что автор этих примеров не владеет HTML в достаточной мере, чтобы написать хоть одну строчку профессиональной статьи! Впрочем, я часто говорю это о пользователях любых фреймворков.
Каждый косяк с failwind, bootcrap и даже «ванильной» версией кода демонстрирует неспособность разработчика работать с чистым HTML, это вообще характерно для многих пользователей фреймворков. Я могу еще долго источать желчь, но все-таки перейду к делу. Давайте посмотрим на конкурс, предложенный автором исходного материала в конце его статьи.
Несостоятельность вариантов, написанных при помощи фреймворков — это одна из моих любимых тем, в своих статьях я часто ее поднимаю. Можете прочитать парочку, чтобы понять, о чем речь. Но сегодня я хочу сосредоточиться на жалкой, кривой и косой попытке обращаться с чистыми «ванильными» HTML и CSS.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- displays site properly based on user's device -->
<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">
<title>Frontend Mentor | Product preview card component</title>
<!-- Feel free to remove these styles or customise in your own stylesheet ???? -->
<link rel='stylesheet' href='./css/normalize.css' />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,700&family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
<link rel='stylesheet' href='./css/main.css' />
</head>
<body>
<div class='main-wrapper'>
<div class='product-card-wrapper'>
<picture class="product-picture">
<source media="(min-width:1024px)" srcset="./images/image-product-desktop.jpg">
<img src="./images/image-product-mobile.jpg" alt="Gabrielle Essence - Eau de
parfum">
</picture>
<div class="product-info-wrapper">
<p class="product-category">Perfume</p>
<h1 class="product-name">Gabrielle Essence Eau de Parfum</h1>
<p class="product-description">
A floral, solar, and voluptous interpretation composed by Olivier
Polge, Perfumer-Creator for the House of CHANEL.
</p>
<div class="product-price-wrapper">
<p class="sales-price">$149.99</p>
<p class="normal-price">$169.99</p>
</div>
<button class="add-to-cart-btn">
<img class="add-to-cart-icon" src="./images/icon-cart.svg" />
<span class="add-to-cart-text">Add to Cart</span>
</button>
</div>
</div>
</div>
</body>
</html>
Пойдем с самого верха. Во-первых, в link'ах стилей не заданы атрибуты media=«screen», PNG иконка существует в единственном размере и не имеет фоллбэков, всюду бесконечные бессмысленные DIV, бесполезные классы, тэги абзаца вокруг каждого кусочка текста, который местами даже не является законченным предложением. Статичные презентационные изображения в разметке, H1, который в реальности следует заменить на H2 или H3, так как название продукта НЕ является заголовком, в который будут входить все подразделы страницы, и т. д. и т.д.
И уже на данном этапе можно заключить, что разметка — полнейший хлам, который незрячие пользователи увидят примерно так:
Господи, да сколько же стоит продукт? Какая цена верна? Незрячему пользователю придется туго, даже человек с орлиным зрением не сможет ему помочь.
Дело не только в разметке
Мало того, что автору плевать, что дизайн, который он хочет сверстать, изначально плох, так еще и его собственные изменения ситуацию не спасают. Тут мы можем наблюдать мелкий шрифт, плохую работу с цветом, и т.д., и т.п…
К счастью, к проекту приложено несколько JPEG того, что автор пытался изобразить.
Теперь мы видим несколько явных недостатков, среди которых дурацкий тонкий шрифт Montserrat невнятного цвета, интервалы, которые пляшут в зависимости от размера контента, но это всё еще не смертельно. По-настоящему плохо то, КАК автор пытается построить этот дизайн в коде. Опять же, давайте посмотрим на «чистый» вариант:
Он ещё менее разборчив за счёт ещё более светлого цвета текста и тонкого шрифта, слишком малой высоты строки и так далее. Ужасающе плохим его делают шрифты размером 12px, что существенно ниже порога читаемости. Это не улучшение, это неумелый беспредел.
Но где ситуация выходит из-под контроля, так это в «мобильной» версии — там пользователю подкладывают целую свинью. План был неплох, но он, увы, провалился.
Из-за несоответствия метрик изменения происходят несвоевременно на всех моих машинах, а хуже всего обстоят дела с медиацентром.
Еще одна подножка для доступности и юзабилити, зародившаяся еще на этапе PSD: если у вас в планах использовать фиксированную ширину, необходимо указать также и максимальную ширину, чтобы часть контента не была вытеснена в нижнюю часть экрана. Чем уже становится экран, тем сильнее всё распадается на части.
Только взгляните на эту безумную таблицу стилей.
Здесь можно наблюдать всю классику дизайнерского невежества. Пиксельно-метрические шрифты, углы, ширины, отступы, поля…
А 2.68 килобайт CSS поверх 6 килобайт всякого нормализационного мусора — это прямо золотой стандарт того, как НЕ надо писать HTML или CSS. Они реально засунули сюда лишние полкило разметки, чтобы не писать полкило CSS…
Именно такой мусор заставляет людей бросаться на SPA, делая свои сайты еще более раздутыми, медленными и недоступными в тех случаях, когда SPA не оправдано.
Итак, как сделать всё правильно?
Я уже сделал рерайт приведенной выше разметки. Это одна карточка, на написание которой я потратил меньше 5 минут времени — и это с учетом кроссбраузерного тестирования результата.
Итак, вот папка, содержащая живую демонстрацию, .rar со всей этой ерундой, а также .txt-версия разметки для тех, кто боится просматривать исходники, и т.д., и т.п.
Давайте посмотрим, как отображается моя версия.
Я использую 0,875rem как наименьший допустимый размер шрифта, 1rem как размер абзаца. Также я поменял цвет на более читаемый и взял шрифт «Poppins», глифы которого чуть потолще. Привел цвета в соответствие, изменил кнопку корзины и улучшил читаемость цены. Добавление слова «was» помогает понять смысл этого контента незрячим пользователям. DEL в старой цене также этому способствует.
Внешний вид на маленьком экране лучше, чем у исходной версии, поскольку мне на самом деле не плевать на пользователей.
Я избавился от закругленных углов и лишних отступов, чтобы было больше свободного места для контента, вставил изображение с генерируемым контентом после заголовка в размере, основанном на EM, чтобы пользователь имел представление о том, на что он смотрит. До этого реальный контент был задвинут далеко вниз экрана. Я переключил всё на выравнивание по центру, которое, ИМХО, всегда лучше выглядит на маленьких дисплеях.
Я также подправил изображение, чтобы продукт был лучше выровнен. Это чертовски раздражало моего внутреннего дизайнера. Да, как бы я ни ругал их и ни высмеивал «художников, которые думают, что они разработчики», я на самом деле и сам своего рода творец. Вот почему неровные padding'и и margin'ы выводят меня из себя.
А теперь отключим отображение стилей — у незрячих пользователей гораздо больше информации. Скриншот не передаёт всей картины, но даже на нём видно, что стало лучше.
Теперь раздел с ценами, по крайней мере, имеет смысл. Отчасти это потому, что я написал его так, как делаю всегда в таких случаях:
- Контент или подобие будущего контента пишется так, будто HTML и CSS даже не существует, поэтому он должен хорошо выглядеть даже в простом текстовом редакторе.
- Размечаем контент с помощью HTML, чтобы указать, что это за шткуи, грамматически и структурно, не заботясь о том, как они выглядят. Помните, если при описании внешнего вида вы оперируете тегами или классами, вам вообще не стоит писать HTML-код.
- Описываем стили для разных экранов в единой монолитной таблице стилей.
Таким образом, если какая-то часть стилей не сработает или не подходит user-agent, страница все равно будет пригодна для использования.
Именно здесь большинство предполагаемых «дизайнеров» и «разработчиков фронтэнда» обычно пускают всё на самотёк, ставя телегу впереди лошади, занимаясь внешним видом, прежде чем подумать о содержании или разметке!
Давайте посмотрим на мой HTML, начиная с doctype и meta.
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta
name="description"
content="This page is a rewrite of a tailwind / bootstrap / vanilla demo that IMHO was a bloated mess"
>
<meta name="twitter:image" property="og:image" content="images/social.jpg">
Я сократил первые несколько тегов до одной строки не для экономии трафика, а в качестве мягкого напоминания о том, что эти теги всегда должны появляться в таком порядке, и между ними не следует вставлять ничего лишнего.
Поскольку charset META должен появляться в документе перед любым CDATA или содержимым атрибута content="" — иначе парсер сдастся и начнет все с начала документа — я поместил все мета-теги вместе перед link, причем charset meta стоит на первом месте! Я добавил описание и изображения для социальных сетей просто потому, что они должны быть там для поиска или предварительного просмотра.
Попутное замечание: знаете ли вы, что поскольку в twitter используется «name», а в opengraph — «property», их можно объединить в одно объявление?
Секция с link'ами:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,700&family=Poppins:wght@400;700&display=swap" media="screen,print">
<link rel="stylesheet" href="rewrite.screen.css" media="screen">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="mask-icon" href="favicon.mask.svg" color="#08A">
<link rel="shortcut icon" href="favicon.ico">
Она до зубовного скрежета стандартна. Обратите внимание, что для шрифта я указываю media=«screen,print», поскольку невизуальным UA должно быть наплевать, какие шрифты ты используешь. Аналогичным образом таблица стилей экранной среды получает media=«screen», чтобы мы не отправляли экранный вид в печать, речь, поиск или любому другому пользовательскому агенту, которому не должно быть дела до нашего экранного вида.
Это концепция, которую, кажется, каждый проклятый фреймворк не в состоянии даже постичь.
Я также взял стоковую иконку из одного моего проекта и применил её должным образом. См. мою статью “All these favicons are getting out of control”, чтобы узнать больше о том, как правильно это делать.
Даже над тегом нужно было немного поработать:
<title>
Product Preview Card Demo -- CutCodeDown Rewrites
</title>
Тег title должен представлять собой заголовок текущей страницы, дефис, а затем заголовок сайта… а на большинстве сайтов заголовок сайта отображается только на главной странице. Вот и все, это формат, которому нужно следовать, ровно то, что должен сообщать, чтобы быть максимально полезным в своей роли. А эта роль заключается в том, чтобы отображаться в рамке окна или в заголовке вкладки, а также в ссылках на страницу.
Не вертикальные черточки, не хрень, набитая ключевыми словами и ТОЛЬКО в этом порядке! ПОНЯТНО ВАМ?!??
Далее…
<h1>Product Preview Card Demo</h1>
<main>
… Я добавил H1 в качестве заголовка страницы/сайта. H1 должен быть заголовком, для которого все прочее на странице является подразделом. Это потому, что H2 означает начало подраздела H1, так же как H3 означает начало подраздела предшествующего ему H2. Вот почему несколько H1 — это тарабарщина, и почему использование H1 внутри подраздела страницы — даже первого — говорит незрячим пользователям, что в структуру сайта им придется въезжать самостоятельно. Неважно, сколько предполагаемых «экспертов» утверждают, что такие вещи, как «баннерные области» или «первый заголовок» должны быть H1, они ни черта не смыслят в доступности страниц!
И, конечно же, основной контент — это основной контент. Поведение центрирования в приведенных автором примерах не должно быть частью самой карточки. Также не следует вставлять для этого DIV, когда у нас есть семантические теги.
Теперь, наконец, мы можем действительно построить карточку:
<section
class="productCard"
style="
--bgImageLarge:url(images/productLarge.jpg);
--bgImageSmall:url(images/productSmall.jpg);
"
>
<header>
<span>Perfume</span>
<h2>Gabrielle Essence <span>Eau de Parfum</span></h2>
</header>
<p>
A floral, solar, and voluptous interpretation composed by Olivier
Polge, Perfumer-Creator for the House of CHANEL.
</p>
<footer>
<strong>$149.99</strong>
<span>Was <del>$169.99</del></span>
<a href="#">Add To Cart</a>
</footer>
<!-- .productCard --></section>
Выглядит просто оскорбительно, учитывая, что это примерно половина всего оригинального кода. Нам понадобится только один класс, если, конечно, мы не боимся применять селекторы и не страдаем всей этой сказочной ерундой, которую невежды оправдывают словами «время рендеринга» или «трудно им следовать».
Карточка — это раздел, так обозначьте вы его как таковой! Всего ОДИН класс, чтобы определить его роль.
Inline-стили — то, против чего я обычно выступаю, — отправляют оба наших изображения в карточку, и их можно показывать опционально. Это исключение из правила, что style="" — это обычно неумелое барахло, потому что мы таким способом контролируем разметку, а не принудительно показываем картинки всем UA, даже тем, которые на них плевать хотели! Это также облегчает добавление/удаление/перемещение изображений там, где это необходимо.
У нас есть очевидный заголовок с категорией и названием продукта, H2, так как это подраздел. Оба span являются хуками для применения стилей, но сами по себе стиль не задают. Верхний, который стоит перед H2, нужен для установки меньшего размера шрифта и верхнего регистра. Тот, что находится внутри H2, получает значение display:inline-block, чтобы работать в качестве аккуратного объединяющего элемента на маленьких экранах.
После заголовка идут абзацы содержимого. Мы не делаем ничего такого, что могло бы оправдать наличие лишней разметки.
И наконец, футер. Цена обернута в strong. Мы хотим подчеркнуть фактическую цену, учитывая, что это цена распродажи. Затем идет span для указания старой цены. Я добавил слово «was» для ясности и использовал DEL в структурных и грамматических целях — цена же старая и больше не актуальна.
И последнее, но не менее важное замечание: я использовал, так как кнопка будет срабатывать по велению скрипта… ну, разве что вы захотите использовать здесь Form — тогда тег будет более уместен.
И мне не понадобился ни один чертов дополнительный класс.
Комментарии (20)
OKyJIucT
26.09.2022 08:32+9Так в чем же заключается провал Tailwind? В том, что автору не нравится использовать много классов, а вся «магия» фреймворка только на них и держится?
Заголовок многообещающий, но в итоге статья скатывается к тому, что автор первой статьи не знает ванильный HTML, а также не слышал про юзабилити и адаптивность.
E11E
26.09.2022 08:54+6Автор конечно негодует правильно по поводу фреймворков и тучи мусорного кода, и мыслит в верном направлении, но самому ему пока не хватает опыта и навыка делать более грамотно в чистом html css, и тем более - в seo :)
Автор - инлайн стили НИ-КОГ-ДА, что неясного?
Вы основную часть SEO, картинку товара!!! прячете в бэкграунд :) Это FIGURE, ТОЛЬКО FIGURE и в ней srsset размеров в img, поисковики должны видеть эту картинку и оценивать как главное на странице.
span-ы в заголовках, - есть в css child-ы по любым условиям, номер слова одно из них, когда сделать перенос, вы же не красите текст, просто переносите его.
section - тэг разметки баров, а не главного контента main - только ARTICLE.
И в header тегах ТОЛЬКО ТЭГИ ЗАГОЛОВКОВ, никаких span-ов с рубриками и прочим.
Но в целом вы мыслите правильно, нужно избавляться от барахла и тонн мусора любителям писать кучи классов и div-ов.
KhodeN
26.09.2022 13:13Тоже смутило. Вроде бы все и правильно, несмотря на экспрессию. Но взять и запихнуть картинку в фон... подрывает доверие к остальному.
Lisaveta_K
26.09.2022 09:14+3Написано конечно так, что подгорит у всех причастных к веб-разработке и вёрстке.
Ах, как накипело у человека то!
Я на таких текстах, всегда выдыхаю и сижу с лицом Мона Лизы, эдакой медитативно-насмешливой улыбочкой. Ведь каждый для себя формирует свои Лучшие практики в пределах поставленных задач, доступного времени и бюджетов.
Читателям напомню, что это перевод, а не оригинальный текст.
Нас познакомили с мнением англоязычного автора, но не хотели задеть.
Fell-x27
26.09.2022 09:26+4Автор: я Давинчи от мира верстки, я ей живу, я ей дышу, семантика - моя вторая сущность! Юзабилити! Ридабилити! Доступность для слепых!
Тот же автор: использует ссылку в контексте кнопки как студент-первокурсник, ломая семантику, ридабилити и доступность для слепых, вводя поисковые системы в заблуждение. Если в магазине товар еще и лочился бы при добавлении в корзину, поисковики бы еще и быстро ликвидность скликали.
Pastoral
26.09.2022 11:05Как человек не причастный к вёрстке, замечу, что всё написанное вызывает тихий ужас. Если что-то стандартно, этого вообще не должно быть. Браузер просто правильно работает сам, и точка.
Идея что какой-то поисковик читает страницы и пытается понять что на них написано - бред, я не хочу основывать никаких решений на таком поисковике, не люблю обман. Будьте любезны сообщить поисковику то, что я должен в нём увидеть, и непременно с указанием паспортных данных, чтобы от ошибки пацанов не пострадали безвинные.
Я заглядывал в "стандарт" HTML - там много слова "may", достаточно одного - и это уже не стандарт.
И так далее и тому подобное. Термин для такого уже отлит - Бредовая работа (Bullshit jobs). Возникает ли она сама собой - у мистиков один ответ, у конспирологов - другой, а кое у кого, скажу так раз уж на ресурсе следует обходиться без оскорблений, ответ да. Можно обсуждать детали, но строго для удовольствия от общения - there is no right way to do a wrong thing (в этой форме древность и авторитетность высказывания нагугливается, ИМХО, лучше всего).
В то далёкое время когда Java испытывала взрывной рост популярности, один аналитик высказался в том духе, что люди бегут не к Java, люди бегут от Win32. Хочется заимствовать - люди бегут от HTML куда угодно, особенно если это значит, что "особенностями" разных браузеров будет заниматься кто-то другой.
O_Nayre
26.09.2022 16:15+2Абстрагируясь от желчи, кода и пр. Ваши примеры не хуже и не лучше Bootstrap, Taliwind, etc. Обычная вкусовщина.
Использовал оба фреймворка и остановился на последнем из-за удобства. Да я не знаю html, css, JS, PHP дальше основ.
Видите ли - я врач. И использование фреймоврков с оптимальной простотой и условно низким порогом вхождения позволило мне создать довольно крупный портал по своей специальности (учитывая то что бюджета на найм студии у меня нет и большинство студий попробует мне впарить такую же вкусовшину на\без фреймворков).
domix32
27.09.2022 02:43Думается проблемы доступности врачей в таком случае мало должны волновать. Не уверен что существует достаточное количество слабовидящих врачей которые бы занимались навигацией со скринридером.
qworin
26.09.2022 16:16Даже если это и перевод, то неполный. Часть со стилизацией примера и довольно эмоциональными выводами просто выкинута ????♂️
ispmanager Автор
26.09.2022 16:17Да, действительно, статья в оригинале объёмная, и пока мы опубликовали лишь первую часть.
antonkrechetov
ispmanager Автор
Спасибо, что обратили внимание! Добавили ссылку на оригинал
diakin
А точно "Автор оригинала: Thomas Dimnet"?
Он же вроде автор предыдущей статьи.
А в этой пишут