[CSS, Клиентская оптимизация] DRY CSS: Как использовать каждое объявление только один раз (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Использование DRY в CSS — это способ максимально избегать повторения в таблицах стилей. Этот подход не панацея, но он достаточно эффективен и является одним из основных методов оптимизации. Поскольку я использовал и изучал его почти 10 лет, в этой статье хочу поделиться своим опытом и знаниями.
А если вам будет интересна тема оптимизации CSS, то я рассказал об основах в моей небольшой книге "CSS Optimization Basics".
Основные шаги
Прежде чем мы углубимся в подробности, как «высушить» таблицы с помощью DRY, обратите внимание, что этот метод нетривиально автоматизировать из-за каскадности. Но, не смотря на это, я постараюсь ничего не упустить.
- Пишите CSS обычным и естественным образом.
- Определитесь с DRY-границами, что вы будете оптимизировать: раздел (функционально разделенные CSS-стили), файл, компонент или @media-запросы. Я работаю на уровне файл/@media, то есть обычно «сушу» всё в максимально возможном объеме.
- Убедитесь, что формат кода является консистентным, так как border:0;, border: 0; и border: none; означают одно и тоже, но это значительно усложняет поиск дубликатов.
- Найдите повторяющиеся объявления:
- Для новых стилей: после первоначальной инициализации.
- Для новых функций и исправлений: после завершения соответствующих действий.
- Совет: если для изменений в файле недостаточно подсказки системы версионирования, просто временно сделайте отступ для измененных объявлений для последующий проверки на уникальность.
- Разрешите повторяющиеся объявления:
- Проверьте каждое объявление (в новых таблицах стилей) или каждое изменённое объявление на предмет повторений в заданном диапазоне (если дедупликация ограничена отдельными разделами, сузьте поиск этими разделами).
- Для каждого повторного объявления (переход к действиям):
- Определите, какое правило в таблице стилей должно быть первым (для этого вы должны определить, какой путь вы выбираете для сортировки селекторов).
- Если первое правило содержит дополнительные объявления, которые еще не были проверены, то скопируйте всё правило и вставьте его после оригинала. Сохраните обнаруженный дубликат в первом правиле и удалите другие объявления, и сделайте наоборот во втором правиле, чтобы оно было похоже на старое правило, только без объявления, которое будет выполняться более одного раза.
- Скопируйте селекторы других правил, которые содержат соответствующее объявление, в правило, идущее первым.
- Обязательно удалите повторяющиеся объявления, селекторы которых были только что скопированы в таблицу стилей, и удалите правило, если оно состоит только из перемещенного дублирующего объявления.
- (Повторите шаги).
- Убедитесь, что правила, обрабатывающие ранее повторяющиеся объявления, содержат селекторы в правильном порядке.
- Убедитесь, что правила, обрабатывающие ранее повторяющиеся объявления, имеют правильное расположение.
Весь этот процесс, на первый взгляд, может показаться запутанным и пугающим, но сейчас мы погрузимся немного глубже и рассмотрим примеры.
Особые случаи
Существует два сценария, требующих особого внимания:
- Разделение файлов: отдельные CSS-файлы могут быть полезны, особенно при повторной сборке в эксплуатацию, но когда дело доходит до «сушки» объявлений, они создают «жесткий» барьер: требуется много усилий для поиска и удаления повторяющихся объявлений. Если мы работаем с небольшой или средней кодовой базой на CSS, то может быть разумно перейти на одну таблицу стилей. Но когда мы имеем дело со сложными таблицами, то некоторое повторение допустимо.
- Строгость подхода или отступление от него: если мы строго избегаем повторений (то есть полностью хотим удалить дубликаты), мы всё равно будем иногда сталкиваться с исключениями. Эти исключения, кроме структурно-зависимых, таких как @media-запросы, файловые границы, или когда последовательность (каскад) является важной, будут вызывать проблемы с поддержкой. Селекторные хаки также являются исключением, поскольку некоторые селекторы работают таким образом, что фактически не позволяют пользовательскому агенту корректно интерпретировать соответствующее правило. В таких случаях мы не можем избежать совпадений, потому что при объединении соответствующих селекторов мы можем повлиять на их работу и результат будет некорректный.
Примеры
Теперь давайте поработаем с несколькими классическими таблицамибез использования препроцессора. Мы сосредоточимся на оптимизации на уровне файла, чтобы можно было представить соответствующий код в виде секции или модуля, который выполняет одно и то же действие.
Оптимизация. Пример первый
Этот пример взят с сайта www.engadget.com, где мы обнаружили 92% повторений, случайный раздел, но по-крайней мере отсортированный в алфавитном порядке. Мы предполагаем, что порядок селекторов нас устраивает, и не будем менять и комментировать имена классов и т. д.
Код
SPL
.arrow-left {
border-color: transparent;
border-style: solid;
border-width: 10px 10px 10px 0;
height: 0;
width: 0;
}
.arrow-down {
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #2b2d32;
bottom: 0;
height: 0;
left: 20px;
width: 0;
}
.faq-list .faq-item-title {
cursor: pointer;
}
.faq-list .faq-item-title:after {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #111;
content: '';
display: inline-block;
float: right;
height: 0;
opacity: .5;
vertical-align: top;
width: 0;
}
#contact input:focus,
#contact textarea:focus {
border: 1px solid #3398db;
}
.flickity-slider>.table {
table-layout: fixed;
}
::selection {
background: #9b59b6;
color: #fff;
}
.videoWrapper {
height: 0;
padding-bottom: 56.25%;
position: relative;
}
.videoWrapper iframe {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.i-rail-followus__socials {
display: table;
}
.i-rail-followus__tw {
vertical-align: sub;
}
Когда мы смотрим на эту таблицу, то сразу хотим быстро удалить повторяющиеся объявления. Но поскольку мы находимся в самом начале «сушки», не будем отходить от алгоритма и просто спускаемся по таблице сверху вниз, просматривая каждое объявление. Первым является border-color: transparent;. Оно где-нибудь еще используется? Нет, тогда идём к следующему — border-style: solid;. Оно уникальное. Тоже самое с border-width: 10px 10px 10px 0;. Затем height: 0;. Не уникальное.
Соответственно, наша работа начинается с height: 0;. Заметим, что это объявление используется в трех различных правилах: .arrow-down, .faq-list .faq-item-title:after и .videoWrapper. Поскольку у нас нет правила, которое включает в себя именно эти четыре селектора, мы копируем их, чтобы сформировать новое правило непосредственно перед тем, в котором мы нашли первое вхождение height: 0;( .arrow-left). Другими словам, мы пишем новое правило только для height: 0;.
.arrow-left,
.arrow-down,
.faq-list .faq-item-title:after,
.videoWrapper {
height: 0;
}
Теперь убираем height: 0; из всех остальных правил. Поскольку ни одно из них не состояло исключительно из этого объявления, мы не можем удалить их целиком (пока). Обычно я делаю это за один шаг: если нахожу «бесспорный» дубликат, то создаю новое правило, ищу больше вхождений, удаляю объявление, которое нужно переместить, и копирую селектор(ы), который нужно вставить. С опытом всё это становится проще.
Продолжим с правилом .arrow-left, с объявлением, следующим после height: 0; — width: 0. Дубликат? Да. И это хорошо, потому что когда мы проверяем, где еще используется width: 0;, то видим, что оно почти такое же, но не идентичное селекторам, использующим height: 0;. То есть мы начнем с нового правила для width: 0;, убедившись, что удалили все предыдущие вхождения:
.arrow-left,
.arrow-down,
.faq-list .faq-item-title:after {
width: 0;
}
Это правило идет после созданного для height: 0; и перед .arrow-letf;, которое мы только что проверили и оптимизировали. Я считаю, что результирующий порядок полезен, потому что предпочитаю, чтобы правила располагались в порядке важности и воздействия. А поскольку мы объединяли правила, то сделали их более эффективными.
Давайте проработаем правило .arrow-down;. В нём нет повторений, хотя его можно описать элегантнее: border: 10px solid transparent; border-top-color: #2b2d32;.
Продолжим с .faq-list .faq-item-title. Тут нет дубликатов. На самом деле этот фрагмент таблицы стилей был довольно простым, поэтому мы больше не находим дополнительных совпадений.
Код
SPL
.arrow-left,
.arrow-down,
.faq-list .faq-item-title:after,
.videoWrapper {
height: 0;
}
.arrow-left,
.arrow-down,
.faq-list .faq-item-title:after {
width: 0;
}
.arrow-left {
border-color: transparent;
border-style: solid;
border-width: 10px 10px 10px 0;
}
.arrow-down {
border-bottom: 10px solid transparent;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #2b2d32;
bottom: 0;
left: 20px;
}
.faq-list .faq-item-title {
cursor: pointer;
}
.faq-list .faq-item-title:after {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #111;
content: '';
display: inline-block;
float: right;
opacity: .5;
vertical-align: top;
}
#contact input:focus,
#contact textarea:focus {
border: 1px solid #3398db;
}
.flickity-slider>.table {
table-layout: fixed;
}
::selection {
background: #9b59b6;
color: #fff;
}
.videoWrapper {
padding-bottom: 56.25%;
position: relative;
}
.videoWrapper iframe {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.i-rail-followus__socials {
display: table;
}
.i-rail-followus__tw {
vertical-align: sub;
}
Оптимизация. Пример второй
Для второго примера возьмём eBay. На этот раз мы тоже хотим просто переформатировать (отступы, сортировка объявлений по алфавиту), но снова сталкиваемся с практиками, которых следует избегать (особенно c именами классов или отсутствием резервных шрифтов, но для шрифтов вроде Arial это не является проблемой).
Код
SPL
.sh-GifCont {
color: #999;
font-family: Verdana !important;
font-size: 10px;
font-weight: normal;
padding: 0 10px 4px 10px;
}
.sh-GetFastImg {
background-image: url('http: //ir.ebaystatic.com/pictures/aw/pics/de/viewitem/spr4VI.png');
background-position: 0 -178px;
background-repeat: no-repeat;
float: left;
height: 16px;
margin-right: 4px;
width: 56px;
}
.sh-float-l {
float: left;
}
.sh-FrZip {
padding: 10px 0 0 15px;
width: 12%;
}
.sh-FrDelLoc {
padding: 10px 15px 0 10px;
width: 10%;
}
.sh-FrCnt {
padding-left: 10px;
padding-right: 0;
text-align: left;
}
.sh-FrZipCnt {
padding: 0 0 0 15px;
}
.sh-FrDelLocCnt {
padding: 0;
}
.sh-FrBtn {
padding: 5px 15px 10px 8px;
}
.sh-FrDelSite {
padding: 6px 0 0;
}
.vi-frs-sh-FrSlctr {
display: inline;
padding: 6px 15px 0 10px;
}
.sh-FrZipDiv {
display: inline;
padding: 6px 15px 0 0;
}
.sh-FrTxt {
color: #333;
font-family: Arial;
font-size: 12px;
font-weight: normal;
padding-left: 15px;
}
.sh-FrLrnMore {
display: inline;
padding: 10px 10px 10px 15px;
}
.sh-FrQuote {
display: inline;
}
.sh-FrLnk {
margin-top: 5px;
}
.sh-Tbl {
padding: 10px;
}
.sh-TblCnt {
color: #333;
font-family: Arial;
font-size: 12px;
font-weight: normal;
padding-left: 15px;
}
.sh-TblHdr {
color: #5d5d5d;
font-family: Verdana;
font-size: 12px;
font-weight: normal;
padding-left: 15px;
}
.sh-Info {
color: #999;
font-family: Arial;
font-size: 11px;
font-weight: normal;
}
.sh-FrSbTxt {
color: #999;
font-family: arial;
font-size: 11px;
font-weight: normal;
padding-left: 15px;
}
.sh-FreightHdr {
color: #333;
font-family: Verdana !important;
font-size: 10px;
font-weight: normal;
padding: 5px 0 5px 23px;
}
.sh-Freight-Hdr {
color: #333;
font-family: Verdana !important;
font-size: 10px;
font-weight: normal;
padding-left: 13px;
}
.sh-Cnt {
color: #5d5d5d;
font-family: Arial;
font-size: small;
font-weight: normal;
padding-left: 13px;
}
.vi-frs-sh-TxtCnt {
color: #333;
font-family: Arial;
font-size: 12px;
font-weight: normal;
}
.sh-BtnTxt {
color: #333;
font-family: Verdana,Tahoma,Arial;
font-size: 12px;
font-weight: normal;
height: 24px;
margin: 0;
padding: 0 3px;
position: relative;
text-decoration: none;
top: 0;
}
.sh-bubble-position {
float: left;
padding-top: 5px;
}
.sh-del-lrge b {
font-size: 15px;
}
.sh-gspFirstLine {
color: #333;
font-family: Arial;
font-size: 15px;
padding: 25px 10px 5px 0;
}
.sh-gspSecondLine {
color: #777;
font-family: Arial;
font-size: 12px;
padding: 0 10px 15px 0;
}
Первый шаг: color: #999; был использован более одного раза? Да. Итак, мы сначала создаем собственное правило:
.sh-GifCont {
color: #999;
}
Следует добавить селекторы для двух других вхождений:
.sh-GifCont,
.sh-Info,
.sh-FrSbTxt {
color: #999;
}
Здесь нам также помогает предположение, что таблица стилей уже использует тот порядок выбора, который нам нужен, и что смена правил не вызовет проблем. Полезно иметь четкое представление о порядке выбора и о решении каскадных проблем, не перемещая затронутые правила или не объединяя их.
font-family: Verdana !important; — это объявление используется трижды. Затем font-size: 10px; — обратите внимание, важно избегать повторения селекторов: это объявление используется теми же селекторами, что мы сгруппировали для «Verdana».
.sh-GifCont,
.sh-FreightHdr,
.sh-Freight-Hdr {
font-family: Verdana !important;
}
.sh-GifCont,
.sh-FreightHdr,
.sh-Freight-Hdr {
font-size: 10px;
}
Резюмируем правила:
.sh-GifCont,
.sh-FreightHdr,
.sh-Freight-Hdr {
font-family: Verdana !important;
font-size: 10px;}
Таким образом мы проработаем всю таблицу стилей, пока не получим:
Код
SPL
.sh-GifCont,
.sh-Info,
.sh-FrSbTxt {
color: #999;
}
.sh-GifCont,
.sh-FreightHdr,
.sh-Freight-Hdr {
font-family: verdana !important;
font-size: 10px;
}
.sh-GifCont,
.sh-FrTxt,
.sh-TblCnt,
.sh-TblHdr,
.sh-Info,
.sh-FrSbTxt,
.sh-FreightHdr,
.sh-Freight-Hdr,
.sh-Cnt,
.vi-frs-sh-TxtCnt,
.sh-BtnTxt {
font-weight: normal;
}
.sh-GifCont {
padding: 0 10px 4px 10px;
}
.sh-GetFastImg,
.sh-float-l,
.sh-bubble-position {
float: left;
}
.sh-GetFastImg {
background-image: url('http: //ir.ebaystatic.com/pictures/aw/pics/de/viewitem/spr4VI.png');
background-position: 0 -178px;
background-repeat: no-repeat;
height: 16px;
margin-right: 4px;
width: 56px;
}
.sh-FrZip {
padding: 10px 0 0 15px;
width: 12%;
}
.sh-FrDelLoc {
padding: 10px 15px 0 10px;
width: 10%;
}
.sh-FrCnt {
padding-left: 10px;
padding-right: 0;
text-align: left;
}
.sh-FrZipCnt {
padding: 0 0 0 15px;
}
.sh-FrDelLocCnt {
padding: 0;
}
.sh-FrBtn {
padding: 5px 15px 10px 8px;
}
.sh-FrDelSite {
padding: 6px 0 0;
}
.vi-frs-sh-FrSlctr,
.sh-FrZipDiv,
.sh-FrLrnMore,
.sh-FrQuote {
display: inline;
}
.vi-frs-sh-FrSlctr {
padding: 6px 15px 0 10px;
}
.sh-FrZipDiv {
padding: 6px 15px 0 0;
}
.sh-FrTxt,
.sh-TblCnt,
.sh-FreightHdr,
.sh-Freight-Hdr,
.vi-frs-sh-TxtCnt,
.sh-BtnTxt,
.sh-gspFirstLine {
color: #333;
}
.sh-FrTxt,
.sh-TblCnt,
.sh-Info,
.sh-FrSbTxt,
.sh-Cnt,
.vi-frs-sh-TxtCnt,
.sh-gspFirstLine,
.sh-gspSecondLine {
font-family: arial;
}
.sh-FrTxt,
.sh-TblCnt,
.sh-TblHdr,
.vi-frs-sh-TxtCnt,
.sh-BtnTxt,
.sh-gspSecondLine {
font-size: 12px;
}
.sh-FrTxt,
.sh-TblCnt,
.sh-TblHdr,
.sh-FrSbTxt {
padding-left: 15px;
}
.sh-FrLrnMore {
padding: 10px 10px 10px 15px;
}
.sh-FrLnk {
margin-top: 5px;
}
.sh-Tbl {
padding: 10px;
}
.sh-TblHdr,
.sh-Cnt {
color: #5d5d5d;
}
.sh-TblHdr {
font-family: verdana;
}
.sh-Info,
.sh-FrSbTxt {
font-size: 11px;
}
.sh-FreightHdr {
padding: 5px 0 5px 23px;
}
.sh-Freight-Hdr,
.sh-Cnt {
padding-left: 13px;
}
.sh-Cnt {
font-size: small;
}
.sh-BtnTxt {
font-family: verdana,tahoma,arial;
height: 24px;
margin: 0;
padding: 0 3px;
position: relative;
text-decoration: none;
top: 0;
}
.sh-bubble-position {
padding-top: 5px;
}
.sh-del-lrge b,
.sh-gspFirstLine {
font-size: 15px;
}
.sh-gspFirstLine {
padding: 25px 10px 5px 0;
}
.sh-gspSecondLine {
color: #777;
padding: 0 10px 15px 0;
}
Редактирование
То, что мы рассмотрели выше, может показаться большой сложной работой. Но всё, что для этого нужно, это воля, практика и понимание, что сложная и утомительная работа возникает только тогда, когда вы выполняете ее с полностью несортированными, неоптимизированными таблицами стилей. Как только мы проясним наши стандарты написания кода и шаги по оптимизации, обновлять и поддерживать таблицы стилей становится довольно просто. Достаточно будет перепроверить свои правки.
Давайте также рассмотрим это очень кратко в третьем примере, отрывке из Code Responsible.
h1,
h2 {
color: #000;
font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif;
font-weight: 400;
line-height: 1.13;
}
h1 {
font-size: 1.86em;
margin: 0 0 .53em;
}
h2 {
counter-increment: counter;
font-size: 1.5em;
margin: 1em 0 0;
}
Здесь мы можем легко изменить правило: предположим, что для h1 нужен другой margin, к примеру, margin: 1em 0 0;. Многие сразу поймут, что мы можем и должны сделать. А чтобы показать один из возможных способов, с более сложной таблицей стилей я поступил бы так.
Первое, что нужно сделать, это внести изменение, отметить его (мой редактор — обычно IntelliJ IDEA — показывает изменения и упрощает их поиск, но мне всё равно нравится временно отступать от новых или измененных объявлений) и протестировать:
h1,
h2 {
color: #000;
font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif;
font-weight: 400;
line-height: 1.13;
}
h1 {
font-size: 1.86em;
margin: 1em 0 0;
}
h2 {
counter-increment: counter;
font-size: 1.5em;
margin: 1em 0 0;
}
Во-вторых, после успешного тестирования я бы проверил все эти измененные строки, не нужно ли их оптимизировать еще раз. Здесь мы обнаружим, что поля для h1 и h2 идентичны.
Следуя способу разбивки на отдельные шаги, создадим правило для h1 и h2. Но у них уже есть собственное правило, поэтому объединим их в одно. Результат:
h1,
h2 {
color: #000;
font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif;
font-weight: 400;
line-height: 1.13;
margin: 1em 0 0;
}
h1 {
font-size: 1.86em;
}
h2 {
counter-increment: counter;
font-size: 1.5em;
}
Этим я хотел показать, что поддерживать таблицы гораздо легче, чем оптимизировать их.
Подсказки
Хочу поделиться несколькими советами (поскольку я обновляю статьи на meiert.com, я могу со временем изменить эти советы).
- Поиск без учета регистра. Вполне возможно, что различие регистра является не случайным (некоторые области таблицы стилей, такие как сгенерированный контент или URL-адреса, могут быть чувствительны к регистру). eBay является хорошим примером: независимо от отсутствующих резервных шрифтов, некоторые из используемых объявлений шрифтов пишутся с заглавной буквы по-разному. Например, мы находим font-family: Arial; и font-family: arial;. Их следует объединить, а значит версия с корректировкой на повторение использует только одно объявление и только в одной нотации (нижний регистр).
- Закрывайте каждое (предварительное) объявление точкой с запятой. Это упрощает просто копирование и перемещение объявлений, а также избавляет нас от множества ложных срабатываний (а их будет несколько). Тег !important является прекрасным примером: если мы ищем «незакрытые» выражения, то border: 0 обязательно совпадёт с border: 0 !important, и может появиться бесконечное количество других действительно разных объявлений. Это усложнит нашу работу и повысит вероятность ошибок.
- Используйте стандартный порядок выбора. Мы не только ограничиваем энтропию таблицы стилей, но и, поскольку новые правила «автоматически» попадают в четко определенные места, получаем естественную линию защиты от повторения селектора. И мы не хотим, чтобы в статьях, подобных этой, селекторы оставались «сухими». Подумайте, можете ли вы использовать мой дизайн упорядочивания селекторов, тем самым помогая сообществу веб-разработчиков стандартизировать его, или создать свой собственный.
Требования к инструментам
Хотя мы продолжаем изучать эффективность этого подхода и способы его улучшения, есть также несколько задач, решение которых наши инструменты могут облегчить.
- Редакторы могут помочь нам избежать повторяющихся объявлений, выделяя их. Лично я думаю, что небольшой символ «!» в конце строки, настраиваемый в каждом редакторе, был бы замечательным решением, как и возможность игнорировать или отключать уведомления для определенных строк. Это значительно упростило бы работу по оптимизации: не только для отслеживания избыточности, но и для получения представления о том, насколько проблематичен тот или иной случай. некоторых случаях таблицы стилей на 90% состоят из повторений.
- Я уверен, у вас остались вопросы; но надеюсь, что их осталось меньше, чем раньше, когда мы в течение многих лет пренебрегали этой оптимизацией. С моей точки зрения, DRY CSS позволил бы нам более трезво взглянуть на переменные и другие функции, которые попали в спецификации CSS.
Эти вопросы, конечно, следует принимать во внимание, и я надеюсь, что вы поможете нам всем поработать над ними. Пример с Яндексомпоказал, что отсутствие повторяющихся объявлений — не панацея. Это помогает сделать CSS компактнее и управляемее, но всё же есть крайние случаи, когда он усложняется. Нам будет полезно изучить эти моменты.
Наконец, я считаю, что избегание повторяющихся объявлений является важным способом работы с CSS. Фактически, я не вижу никакого другого метода оптимизации, помимо создания ваших личных рекомендаций по коду, потому что без систематического подхода к на предотвращению повторения вся наша работа просто увеличивает энтропию, которая не помогает писать качественный код. Но именно к нему мы стремимся как профессионалы. Давайте уделим больше внимания качеству кода и парадигме DRY CSS, и посмотрим, что мы можем автоматизировать, не забывая о своем мастерстве.
===========
Источник:
habr.com
===========
===========
Автор оригинала: Jens Oliver Meiert
===========Похожие новости:
- [CSS, История IT] Языки, которые почти стали CSS
- [Python, Программирование] Каверзные вопросы по Python
- [Разработка веб-сайтов, CSS, JavaScript, Программирование, HTML] Современный стартовый HTML-шаблон
- [Клиентская оптимизация, Управление сообществом, Управление e-commerce, Контент-маркетинг, Email-маркетинг] What is an SEO Company?
- [Информационная безопасность, Big Data, Data Engineering] Модели угроз в дифференциальной приватности (перевод)
- [Высокая производительность, Разработка веб-сайтов, JavaScript, Клиентская оптимизация, ReactJS] Производительность приложений, работающих с Video и Audio
- [Разработка веб-сайтов, CSS] Masonry-раскладка на чистом CSS Grid Level 3 (перевод)
- [VueJS, TypeScript] vuex + typescript = vuexok. Велосипед, который поехал и обогнал всех
- [Разработка веб-сайтов, JavaScript, Программирование, VueJS] Vue 3 на Typescript
- [Python, Java] Удав укрощает Graal VM
Теги для поиска: #_css, #_klientskaja_optimizatsija (Клиентская оптимизация), #_frontend, #_css, #_optimization, #_dont_repeat_yourself, #_blog_kompanii_domklik (
Блог компании ДомКлик
), #_css, #_klientskaja_optimizatsija (
Клиентская оптимизация
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 26-Ноя 01:05
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Использование DRY в CSS — это способ максимально избегать повторения в таблицах стилей. Этот подход не панацея, но он достаточно эффективен и является одним из основных методов оптимизации. Поскольку я использовал и изучал его почти 10 лет, в этой статье хочу поделиться своим опытом и знаниями. А если вам будет интересна тема оптимизации CSS, то я рассказал об основах в моей небольшой книге "CSS Optimization Basics". Основные шаги Прежде чем мы углубимся в подробности, как «высушить» таблицы с помощью DRY, обратите внимание, что этот метод нетривиально автоматизировать из-за каскадности. Но, не смотря на это, я постараюсь ничего не упустить.
Весь этот процесс, на первый взгляд, может показаться запутанным и пугающим, но сейчас мы погрузимся немного глубже и рассмотрим примеры. Особые случаи Существует два сценария, требующих особого внимания:
Примеры Теперь давайте поработаем с несколькими классическими таблицамибез использования препроцессора. Мы сосредоточимся на оптимизации на уровне файла, чтобы можно было представить соответствующий код в виде секции или модуля, который выполняет одно и то же действие. Оптимизация. Пример первый Этот пример взят с сайта www.engadget.com, где мы обнаружили 92% повторений, случайный раздел, но по-крайней мере отсортированный в алфавитном порядке. Мы предполагаем, что порядок селекторов нас устраивает, и не будем менять и комментировать имена классов и т. д. КодSPL.arrow-left {
border-color: transparent; border-style: solid; border-width: 10px 10px 10px 0; height: 0; width: 0; } .arrow-down { border-bottom: 10px solid transparent; border-left: 10px solid transparent; border-right: 10px solid transparent; border-top: 10px solid #2b2d32; bottom: 0; height: 0; left: 20px; width: 0; } .faq-list .faq-item-title { cursor: pointer; } .faq-list .faq-item-title:after { border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #111; content: ''; display: inline-block; float: right; height: 0; opacity: .5; vertical-align: top; width: 0; } #contact input:focus, #contact textarea:focus { border: 1px solid #3398db; } .flickity-slider>.table { table-layout: fixed; } ::selection { background: #9b59b6; color: #fff; } .videoWrapper { height: 0; padding-bottom: 56.25%; position: relative; } .videoWrapper iframe { height: 100%; left: 0; position: absolute; top: 0; width: 100%; } .i-rail-followus__socials { display: table; } .i-rail-followus__tw { vertical-align: sub; } Когда мы смотрим на эту таблицу, то сразу хотим быстро удалить повторяющиеся объявления. Но поскольку мы находимся в самом начале «сушки», не будем отходить от алгоритма и просто спускаемся по таблице сверху вниз, просматривая каждое объявление. Первым является border-color: transparent;. Оно где-нибудь еще используется? Нет, тогда идём к следующему — border-style: solid;. Оно уникальное. Тоже самое с border-width: 10px 10px 10px 0;. Затем height: 0;. Не уникальное. Соответственно, наша работа начинается с height: 0;. Заметим, что это объявление используется в трех различных правилах: .arrow-down, .faq-list .faq-item-title:after и .videoWrapper. Поскольку у нас нет правила, которое включает в себя именно эти четыре селектора, мы копируем их, чтобы сформировать новое правило непосредственно перед тем, в котором мы нашли первое вхождение height: 0;( .arrow-left). Другими словам, мы пишем новое правило только для height: 0;. .arrow-left,
.arrow-down, .faq-list .faq-item-title:after, .videoWrapper { height: 0; } Теперь убираем height: 0; из всех остальных правил. Поскольку ни одно из них не состояло исключительно из этого объявления, мы не можем удалить их целиком (пока). Обычно я делаю это за один шаг: если нахожу «бесспорный» дубликат, то создаю новое правило, ищу больше вхождений, удаляю объявление, которое нужно переместить, и копирую селектор(ы), который нужно вставить. С опытом всё это становится проще. Продолжим с правилом .arrow-left, с объявлением, следующим после height: 0; — width: 0. Дубликат? Да. И это хорошо, потому что когда мы проверяем, где еще используется width: 0;, то видим, что оно почти такое же, но не идентичное селекторам, использующим height: 0;. То есть мы начнем с нового правила для width: 0;, убедившись, что удалили все предыдущие вхождения: .arrow-left,
.arrow-down, .faq-list .faq-item-title:after { width: 0; } Это правило идет после созданного для height: 0; и перед .arrow-letf;, которое мы только что проверили и оптимизировали. Я считаю, что результирующий порядок полезен, потому что предпочитаю, чтобы правила располагались в порядке важности и воздействия. А поскольку мы объединяли правила, то сделали их более эффективными. Давайте проработаем правило .arrow-down;. В нём нет повторений, хотя его можно описать элегантнее: border: 10px solid transparent; border-top-color: #2b2d32;. Продолжим с .faq-list .faq-item-title. Тут нет дубликатов. На самом деле этот фрагмент таблицы стилей был довольно простым, поэтому мы больше не находим дополнительных совпадений. КодSPL.arrow-left,
.arrow-down, .faq-list .faq-item-title:after, .videoWrapper { height: 0; } .arrow-left, .arrow-down, .faq-list .faq-item-title:after { width: 0; } .arrow-left { border-color: transparent; border-style: solid; border-width: 10px 10px 10px 0; } .arrow-down { border-bottom: 10px solid transparent; border-left: 10px solid transparent; border-right: 10px solid transparent; border-top: 10px solid #2b2d32; bottom: 0; left: 20px; } .faq-list .faq-item-title { cursor: pointer; } .faq-list .faq-item-title:after { border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #111; content: ''; display: inline-block; float: right; opacity: .5; vertical-align: top; } #contact input:focus, #contact textarea:focus { border: 1px solid #3398db; } .flickity-slider>.table { table-layout: fixed; } ::selection { background: #9b59b6; color: #fff; } .videoWrapper { padding-bottom: 56.25%; position: relative; } .videoWrapper iframe { height: 100%; left: 0; position: absolute; top: 0; width: 100%; } .i-rail-followus__socials { display: table; } .i-rail-followus__tw { vertical-align: sub; } Оптимизация. Пример второй Для второго примера возьмём eBay. На этот раз мы тоже хотим просто переформатировать (отступы, сортировка объявлений по алфавиту), но снова сталкиваемся с практиками, которых следует избегать (особенно c именами классов или отсутствием резервных шрифтов, но для шрифтов вроде Arial это не является проблемой). КодSPL.sh-GifCont {
color: #999; font-family: Verdana !important; font-size: 10px; font-weight: normal; padding: 0 10px 4px 10px; } .sh-GetFastImg { background-image: url('http: //ir.ebaystatic.com/pictures/aw/pics/de/viewitem/spr4VI.png'); background-position: 0 -178px; background-repeat: no-repeat; float: left; height: 16px; margin-right: 4px; width: 56px; } .sh-float-l { float: left; } .sh-FrZip { padding: 10px 0 0 15px; width: 12%; } .sh-FrDelLoc { padding: 10px 15px 0 10px; width: 10%; } .sh-FrCnt { padding-left: 10px; padding-right: 0; text-align: left; } .sh-FrZipCnt { padding: 0 0 0 15px; } .sh-FrDelLocCnt { padding: 0; } .sh-FrBtn { padding: 5px 15px 10px 8px; } .sh-FrDelSite { padding: 6px 0 0; } .vi-frs-sh-FrSlctr { display: inline; padding: 6px 15px 0 10px; } .sh-FrZipDiv { display: inline; padding: 6px 15px 0 0; } .sh-FrTxt { color: #333; font-family: Arial; font-size: 12px; font-weight: normal; padding-left: 15px; } .sh-FrLrnMore { display: inline; padding: 10px 10px 10px 15px; } .sh-FrQuote { display: inline; } .sh-FrLnk { margin-top: 5px; } .sh-Tbl { padding: 10px; } .sh-TblCnt { color: #333; font-family: Arial; font-size: 12px; font-weight: normal; padding-left: 15px; } .sh-TblHdr { color: #5d5d5d; font-family: Verdana; font-size: 12px; font-weight: normal; padding-left: 15px; } .sh-Info { color: #999; font-family: Arial; font-size: 11px; font-weight: normal; } .sh-FrSbTxt { color: #999; font-family: arial; font-size: 11px; font-weight: normal; padding-left: 15px; } .sh-FreightHdr { color: #333; font-family: Verdana !important; font-size: 10px; font-weight: normal; padding: 5px 0 5px 23px; } .sh-Freight-Hdr { color: #333; font-family: Verdana !important; font-size: 10px; font-weight: normal; padding-left: 13px; } .sh-Cnt { color: #5d5d5d; font-family: Arial; font-size: small; font-weight: normal; padding-left: 13px; } .vi-frs-sh-TxtCnt { color: #333; font-family: Arial; font-size: 12px; font-weight: normal; } .sh-BtnTxt { color: #333; font-family: Verdana,Tahoma,Arial; font-size: 12px; font-weight: normal; height: 24px; margin: 0; padding: 0 3px; position: relative; text-decoration: none; top: 0; } .sh-bubble-position { float: left; padding-top: 5px; } .sh-del-lrge b { font-size: 15px; } .sh-gspFirstLine { color: #333; font-family: Arial; font-size: 15px; padding: 25px 10px 5px 0; } .sh-gspSecondLine { color: #777; font-family: Arial; font-size: 12px; padding: 0 10px 15px 0; } Первый шаг: color: #999; был использован более одного раза? Да. Итак, мы сначала создаем собственное правило: .sh-GifCont {
color: #999; } Следует добавить селекторы для двух других вхождений: .sh-GifCont,
.sh-Info, .sh-FrSbTxt { color: #999; } Здесь нам также помогает предположение, что таблица стилей уже использует тот порядок выбора, который нам нужен, и что смена правил не вызовет проблем. Полезно иметь четкое представление о порядке выбора и о решении каскадных проблем, не перемещая затронутые правила или не объединяя их. font-family: Verdana !important; — это объявление используется трижды. Затем font-size: 10px; — обратите внимание, важно избегать повторения селекторов: это объявление используется теми же селекторами, что мы сгруппировали для «Verdana». .sh-GifCont,
.sh-FreightHdr, .sh-Freight-Hdr { font-family: Verdana !important; } .sh-GifCont, .sh-FreightHdr, .sh-Freight-Hdr { font-size: 10px; } Резюмируем правила: .sh-GifCont,
.sh-FreightHdr, .sh-Freight-Hdr { font-family: Verdana !important; font-size: 10px;} Таким образом мы проработаем всю таблицу стилей, пока не получим: КодSPL.sh-GifCont,
.sh-Info, .sh-FrSbTxt { color: #999; } .sh-GifCont, .sh-FreightHdr, .sh-Freight-Hdr { font-family: verdana !important; font-size: 10px; } .sh-GifCont, .sh-FrTxt, .sh-TblCnt, .sh-TblHdr, .sh-Info, .sh-FrSbTxt, .sh-FreightHdr, .sh-Freight-Hdr, .sh-Cnt, .vi-frs-sh-TxtCnt, .sh-BtnTxt { font-weight: normal; } .sh-GifCont { padding: 0 10px 4px 10px; } .sh-GetFastImg, .sh-float-l, .sh-bubble-position { float: left; } .sh-GetFastImg { background-image: url('http: //ir.ebaystatic.com/pictures/aw/pics/de/viewitem/spr4VI.png'); background-position: 0 -178px; background-repeat: no-repeat; height: 16px; margin-right: 4px; width: 56px; } .sh-FrZip { padding: 10px 0 0 15px; width: 12%; } .sh-FrDelLoc { padding: 10px 15px 0 10px; width: 10%; } .sh-FrCnt { padding-left: 10px; padding-right: 0; text-align: left; } .sh-FrZipCnt { padding: 0 0 0 15px; } .sh-FrDelLocCnt { padding: 0; } .sh-FrBtn { padding: 5px 15px 10px 8px; } .sh-FrDelSite { padding: 6px 0 0; } .vi-frs-sh-FrSlctr, .sh-FrZipDiv, .sh-FrLrnMore, .sh-FrQuote { display: inline; } .vi-frs-sh-FrSlctr { padding: 6px 15px 0 10px; } .sh-FrZipDiv { padding: 6px 15px 0 0; } .sh-FrTxt, .sh-TblCnt, .sh-FreightHdr, .sh-Freight-Hdr, .vi-frs-sh-TxtCnt, .sh-BtnTxt, .sh-gspFirstLine { color: #333; } .sh-FrTxt, .sh-TblCnt, .sh-Info, .sh-FrSbTxt, .sh-Cnt, .vi-frs-sh-TxtCnt, .sh-gspFirstLine, .sh-gspSecondLine { font-family: arial; } .sh-FrTxt, .sh-TblCnt, .sh-TblHdr, .vi-frs-sh-TxtCnt, .sh-BtnTxt, .sh-gspSecondLine { font-size: 12px; } .sh-FrTxt, .sh-TblCnt, .sh-TblHdr, .sh-FrSbTxt { padding-left: 15px; } .sh-FrLrnMore { padding: 10px 10px 10px 15px; } .sh-FrLnk { margin-top: 5px; } .sh-Tbl { padding: 10px; } .sh-TblHdr, .sh-Cnt { color: #5d5d5d; } .sh-TblHdr { font-family: verdana; } .sh-Info, .sh-FrSbTxt { font-size: 11px; } .sh-FreightHdr { padding: 5px 0 5px 23px; } .sh-Freight-Hdr, .sh-Cnt { padding-left: 13px; } .sh-Cnt { font-size: small; } .sh-BtnTxt { font-family: verdana,tahoma,arial; height: 24px; margin: 0; padding: 0 3px; position: relative; text-decoration: none; top: 0; } .sh-bubble-position { padding-top: 5px; } .sh-del-lrge b, .sh-gspFirstLine { font-size: 15px; } .sh-gspFirstLine { padding: 25px 10px 5px 0; } .sh-gspSecondLine { color: #777; padding: 0 10px 15px 0; } Редактирование То, что мы рассмотрели выше, может показаться большой сложной работой. Но всё, что для этого нужно, это воля, практика и понимание, что сложная и утомительная работа возникает только тогда, когда вы выполняете ее с полностью несортированными, неоптимизированными таблицами стилей. Как только мы проясним наши стандарты написания кода и шаги по оптимизации, обновлять и поддерживать таблицы стилей становится довольно просто. Достаточно будет перепроверить свои правки. Давайте также рассмотрим это очень кратко в третьем примере, отрывке из Code Responsible. h1,
h2 { color: #000; font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif; font-weight: 400; line-height: 1.13; } h1 { font-size: 1.86em; margin: 0 0 .53em; } h2 { counter-increment: counter; font-size: 1.5em; margin: 1em 0 0; } Здесь мы можем легко изменить правило: предположим, что для h1 нужен другой margin, к примеру, margin: 1em 0 0;. Многие сразу поймут, что мы можем и должны сделать. А чтобы показать один из возможных способов, с более сложной таблицей стилей я поступил бы так. Первое, что нужно сделать, это внести изменение, отметить его (мой редактор — обычно IntelliJ IDEA — показывает изменения и упрощает их поиск, но мне всё равно нравится временно отступать от новых или измененных объявлений) и протестировать: h1,
h2 { color: #000; font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif; font-weight: 400; line-height: 1.13; } h1 { font-size: 1.86em; margin: 1em 0 0; } h2 { counter-increment: counter; font-size: 1.5em; margin: 1em 0 0; } Во-вторых, после успешного тестирования я бы проверил все эти измененные строки, не нужно ли их оптимизировать еще раз. Здесь мы обнаружим, что поля для h1 и h2 идентичны. Следуя способу разбивки на отдельные шаги, создадим правило для h1 и h2. Но у них уже есть собственное правило, поэтому объединим их в одно. Результат: h1,
h2 { color: #000; font-family: futurastd-book, futura, 'droid sans', 'helvetica neue', helvetica, sans-serif; font-weight: 400; line-height: 1.13; margin: 1em 0 0; } h1 { font-size: 1.86em; } h2 { counter-increment: counter; font-size: 1.5em; } Этим я хотел показать, что поддерживать таблицы гораздо легче, чем оптимизировать их. Подсказки Хочу поделиться несколькими советами (поскольку я обновляю статьи на meiert.com, я могу со временем изменить эти советы).
Требования к инструментам Хотя мы продолжаем изучать эффективность этого подхода и способы его улучшения, есть также несколько задач, решение которых наши инструменты могут облегчить.
Эти вопросы, конечно, следует принимать во внимание, и я надеюсь, что вы поможете нам всем поработать над ними. Пример с Яндексомпоказал, что отсутствие повторяющихся объявлений — не панацея. Это помогает сделать CSS компактнее и управляемее, но всё же есть крайние случаи, когда он усложняется. Нам будет полезно изучить эти моменты. Наконец, я считаю, что избегание повторяющихся объявлений является важным способом работы с CSS. Фактически, я не вижу никакого другого метода оптимизации, помимо создания ваших личных рекомендаций по коду, потому что без систематического подхода к на предотвращению повторения вся наша работа просто увеличивает энтропию, которая не помогает писать качественный код. Но именно к нему мы стремимся как профессионалы. Давайте уделим больше внимания качеству кода и парадигме DRY CSS, и посмотрим, что мы можем автоматизировать, не забывая о своем мастерстве. =========== Источник: habr.com =========== =========== Автор оригинала: Jens Oliver Meiert ===========Похожие новости:
Блог компании ДомКлик ), #_css, #_klientskaja_optimizatsija ( Клиентская оптимизация ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 26-Ноя 01:05
Часовой пояс: UTC + 5