Хабрахабр

Кастомный подход для нормализации и сброса стилей (custom-reset.css)

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

Он заточен именно под кросбраузерность, что очень важно. Почему нормалайз, а не ресет. д. Но в чистом виде он меня вообще не устраивал, различные отступы, бордеры и т. Файл получился довольно универсальный, но все же перед подготовкой проэкта в него нужно заглядывать и возможно что-то коректировать. только мешали, потому я немного подогнал его под свои потребности, поудаляв то, что мне было не нужно.
Со временем файл разрастался, лишнее из нормалайза удалялось, недостающее добавлялось.
Основной целью его создания было максимально подготовить основу для любого проэкта, что по-моему получилось, даже очень удачно.

Надеюсь вы подчеркнете для себя что-то полезное, здесь вы можете ознакомиться с ним.
custom-reset.css

Краткое описание

  • Возможность изменения тегов без ущерба верстке. Что соответствует принципу DRY ( — минимизация объема редактирования, необходимого для внесения изменений).
  • Полное обнуление браузерных стилей.
    То что элемент имеет стили по дефолту совершенно не значит, что они будут нужны именно в том, месте где используется этот тег.
  • Нормализация нужных браузерных штук.
  • IE 10+
  • Некоторые простые полезные снипеты.
  • и советы

Определение блочной модели

*,
*:before,
*:after { box-sizing: inherit;
} html { box-sizing: border-box;
}

Такое определение дает возможность переопределить box-sizing, в случае необходимости, для определенной области, например, если на проект был добавлен компомент у которого был box-sizing: content-box;

Базовые настройки

body { margin: 0; background-color: #fff; line-height: 1.15; text-rendering: optimizeLegibility; text-decoration-skip: objects; -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent;
}

  • text-rendering — определяет как браузеру оптимизировать рендеринг текста.
    optimizeLegibility – качественное отображение важнее скорости, разрешает кернинг и лигатуры.
  • text-decoration-skip: objects;
    Делает подчеркивание с помощью text-decoration: underline; необрывистым (там где это работает).

  • -webkit-text-size-adjust: 100%; — запретить корректировку размера шрифта после изменения ориентации в iOS.
  • -webkit-font-smoothing: antialiased; — делает текст более тонким в Сафари на Маках (начертание сглаженное и четкое одновременно, приятно читать.).
  • -webkit-tap-highlight-color: transparent; — убирает синее подсвечивание при клике на девайсах.

focus это важно, а outline нет


:focus { outline: none;
}

Состояние фокуса это очень важный момент для взаимодействия с интерективными элементами. (Как и почему здесь). Но outline зачастую не вписывается в дизайн. И сами дизайнеры редко прорисовывают это состоние, потому частой практикой стало дублирование стилей ховера.

Это ленивый способ.


.no-touch
}

Нормальные дизайнеры всегда прорисовывают состояние фокуса.

Три основных состояния должны всегда присутствовать на каждом интерактивном элементе (:hover, :focus, :active).

→ Codepen

Отступы

Отступы обнулены, текстовые свойства наследуются.


p,
dd,
dl,
figure,
blockquote { margin: 0;
}
/* Совутую не забывать о списке определений <dl>. Семантика это хорошо.
Для более удобного использования можно позьзоваться дивом (валидно):
dl>div*3>dd{value}+dt{prop} */ blockquote, q { quotes: none;
} ul,
ol { padding: 0; margin: 0; list-style-type: none;
} table { border-collapse: collapse; border-spacing: 0;
} th { font-weight: inherit;
} h1,
h2,
h3,
h4,
h5,
h6 { margin: 0; font-size: inherit; font-weight: inherit;
} audio,
video { display: block;
} img { display: block; border: none; /*max-width: 100%;*/
} iframe { border: none;
} pre,
code,
kbd,
samp { font-family: monospace, monospace; font-size: inherit;
}

Если вам нужны отступы для пользовательского контента (а они нужны), должен быть свой класс обертка и свой стайлгайд.

Пример:


.description { h1, h2, h3, h4 { /* style */ } p { /* style */ } /* и т. д. */
}

Текстовый контент тоже нужно уметь правильно верстать выставляя правильные отступы и высоту строки.

Вот статья на эту тему.

О том, каким может быть пользовательский контент:

Текстовые элементы

Полное наследование. Ссылки больше не синие, стронг не болд, ем не италик. Em, strong это семантические элементы, они используются не для оформления. Например для названиях товаров, в карточках. То что они имеют по дефолту стили не значит, что они будут нужны именно в том, месте где используется этот тег.

Цвет и подчеркивание ссылки мешает когда эта ссылка в виде кнопки или в виде большой кнопки с картинкой и текстом.


a { background-color: transparent; text-decoration: none; color: inherit;
} abbr { border: none; text-decoration: none;
} b,
strong { font-weight: inherit;
} i,
em { font-style: inherit;
} dfn { font-style: inherit;
} mark { background-color: transparent; color: inherit;
} small { font-size: inherit;
} sub,
sup { position: relative; vertical-align: baseline; font-size: inherit; line-height: 0;
} sub { bottom: -.25em;
} sup { top: -.5em;
}

Элементы форм:

Удаляются полностью стили присвоенные кнопкам и инпутам, что может кому-то показаться спорным.

Бывает, возникают неудобства с кнопками при смене тегов, чаще всего это бывает с ссылки на кнопку и наоборот.


button,
input,
optgroup,
select,
textarea { padding: 0; margin: 0; border: none; border-radius: 0; box-shadow: none; background-color: transparent; font: inherit; /* По дефолту, шрифтовые свойства, для этих элементов не наследуются */ color: inherit; letter-spacing: inherit;
} button,
input { overflow: visible;
} button,
select { text-align: left; text-transform: none;
} button,
[type='button'],
[type='reset'],
[type='submit'] { cursor: pointer; -webkit-appearance: none;
} textarea { resize: none; overflow-y: auto; overflow-x: hidden;
} button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner { border: none; padding: 0;
} button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring { outline: none;
} [type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button { height: auto;
} [type='search']::-webkit-search-decoration { -webkit-appearance: none;
} [type='search'] { outline: none;
} ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; }

(Тег button нельзя использовать как флекс контейнер. На IOSах сломается.)

fieldset и legend


fieldset { padding: 0; margin: 0; border: none;
} legend { display: block; padding: 0; white-space: normal;
}

Часто встречал, что эти семантические элементы форм использовались в декоратиыных целях.

Для такого:

Вот пару примров с нормальной реализацией: Никогда так не делайте, это пример худшей практики.

→ Пример 1, пример 2

Не работает просто.) (Тег fieldset нельзя использовать как флекс контейнер.

select

Отменяем стандартное отображение select'а


select { -webkit-appearance: none; -moz-appearance: none; appearance: none;
} select::-ms-expand { display: none;
}

→ Оформляем select сами: codepen

placeholder


::-webkit-input-placeholder { color: inherit; opacity: 1; transition: opacity .3s;
} ::-moz-placeholder { color: inherit; opacity: 1; transition: opacity .3s;
} :-moz-placeholder { color: inherit; opacity: 1; transition: opacity .3s;
} :-ms-input-placeholder { color: inherit; opacity: 1; transition: opacity .3s;
} :focus::-webkit-input-placeholder { opacity: 0;
} :focus::-moz-placeholder { opacity: 0;
} :focus:-moz-placeholder { opacity: 0;
} :focus:-ms-input-placeholder { opacity: 0;
}

Плейсхолдер наслудует цвет. Исчезает при фокусе.

svg (работа с иконками)

Тег svg хоть и полноценный тег, который поддерживает любые свойства, я всегда использую для него обертку, которой и задаю размеры и цвет. Такой подход очень удобный для работы с спрайтами 2-х типов.

Расскажу, как мы работаем с иконками:

Иконочный шрифт мы не используем.

У нас есть 2 типа иконок:

— одноцветные
— цветные (иконки и мелкие изображения).

Все они в формате svg.

Выглядит это так: Для одноцветных используется svg спрайт, котрых хранится отдельно, и кешируется.


<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol id="search" viewBox="0 0 24 24"> <path></path> </symbol>
</svg>

И инклюдится на страницу он так:


<svg class="alert__ico"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../img/sprites/sprite.svg#search"></use>
</svg>

И стили для него: (этот код добавляется в файл)


svg { display: block; width: 100%; height: 100%; fill: currentColor;
}

Для цветных используется css спрайт:


.icon-ico-color:after { background-image: url("data:image/svg+xml,%3Csvg%20width%3D...;
}

И стили для него:


[class*='icon-']:after { content: ''; display: block; width: 100%; height: 100%; background-size: contain; background-position: center; background-repeat: no-repeat; }

Загружается css спрайт асинхронно


<script> $(document).ready(function() { $("head").append("<link rel='stylesheet' type='text/css' href='../css/icons.min.css' />"); })
</script>

Генерируется это, понятное дело, галпом.

Что дает такой подход

Для иконки делается контейнер нужного размера и не зависимо от того, будет иконка цветной или нет, она в него отлично впишется.


<div class="elem__ico"> <svg class="alert__ico"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../img/sprites/sprite.svg#search"></use> </svg>
</div> <div class="elem__ico icon-ico-color"></div>

hidden


[hidden] { display: none; // IE10
}

Атрибут, который скрывает элемент. Пригодится.

:disabled


:disabled,
.disabled { cursor: not-allowed;
}

Правильный курсор. Так как задизейбленной кнопкой может быть ссылка, то псевдокласс уже не сработает, так как ссылка не элемент формы. Для этого добавляйте класс.

::-ms-clear

Псевдоэлемент в инпуте IE для очистки текста.


::-ms-clear { display: none;
}

Убираем его.

:-webkit-autofill


:-webkit-autofill { box-shadow: 0 0 100px #fff inset; -webkit-text-fill-color: currentColor;
}

С помощью внутренней тени закрашиваем этот псевдоэлемент под нужный цвет. И наследует заданный цвет.

::selection


::selection { color: #fff; background-color: #004fe4;
}

Классы

.clearfix


.clearfix:after { content: ''; display: block; clear: both;
}

Хоть сейчас во всю используются флексы, не стоит забывать про флоаты, и тем более не стоит забывать про чистку потока для флоатов.

.visually-hidden


.visually-hidden { position: absolute; z-index: -1; width: 0; height: 0; padding: 0; margin: 0; border: none; overflow: hidden;
}

Для семантики: Когда надо спрятать заголовок, который должен быть, но его нет в дизайне. Скрытие этим способом не игнорируется скринридером.

Для кастомизация цекбоксов/радиобаттонов:

Скрывать с помощью display: none; или атрибута hidden плохая идея, так как инпут теряет способность получать фокус, а фокус (как мы знаем) это важно.

А если скрывать с помощью класса .visually-hidden то инпут не теряет способность получать фокус.

Метод «padding-bottom» для изображений (.cover-pic, .contain-pic.)

В работе с изображениями, а именно с тегом

<img>

есть некоторые сложности:

  • Пока изображение не загрузилось, оно не имеет высоты, что обычно приводит к дерганью верстки при подгрузке.
  • Если изображение не загрузилось, верстка может «ломаться».
  • Не подходящие размеры и пропорции изображений.

Метод «padding-bottom» отлично подходит для решения этих проблем. Контроль размеров изображения происходит за счет обертки.

<div class="img-wrap"> <img src="" alt=""> </div>

Но нельзя просто задать высоту обертке или изображению, потому что при ресайте страницы потеряются нужные пропорции.

Как известно padding в % берет значение ширины родителя, не зависимо заданы вертикальные или горизонтальные значения. И чтоб этого не происходило, высота задается за счет padding в % для псевдоэлемента обертки (:before).

(padding в % некоректно отображается в мозиле, если он задан флекс итему).


.img-wrap { position: relative; width: 30%;
} .img-wrap:before { content: ''; display: block; padding-bottom: 60%;
}

Само изображение нужно спозиционировать абсолютно относительно обертки. Когда необходимо, чтоб изображение занимало все пространство (на подобии background-size: cover;). Используется класс .cover-pic


.cover-pic,
.contain-pic { position: absolute; top: 0; left: 0; width: 100%; height: 100%;
} .cover-pic { object-fit: cover;
} .contain-pic { object-fit: contain;
}

Когда необходимо, чтоб изображение занимало не все пространство (на подобии background-size: contain;). Используется класс .contain-pic

В итоге получается:

  • Изображение резинится.
  • Имеет нужные пропорции (заданы дизайном).
  • Не дергает контент при подгрузке.

Из недостатков: Поддержка object-fit IE. Потому приходится использовать полифил.

→ Пример

Прижатие футера

body { display: flex; flex-direction: column; min-height: 100vh;
} .footer-page { margin-top: auto;
}

Фикс при прижатии футера для IE. В блоке с min-height (которым в данном случае служит body) flex некоректно работает.


@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { html { display: flex; flex-direction: column; }
}

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

100vh на IOS будет немного больше экрана и будет скролл, при наличии адресной строки.

→ Codepen

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

Вопросы и предложения, идеи и замечания приветствуются. Спасибо, что прочитали мою статью, надеюсь она будет вам полезна.

S. Советую ознакомиться с публикацией Организация отступов в верстке (margin/padding). P. И кому интересно, может решить css задачку. И советую использовать css линтеры.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»