Здесь я поделюсь своими наработками для нормализации и сброса стилей.
За несколько лет у меня сформировался небольшой файл, за основу которого, изначально, был взят нормалайз.
Почему нормалайз, а не ресет. Он заточен именно под кросбраузерность, что очень важно. Но в чистом виде он меня вообще не устраивал, различные отступы, бордеры и т. д. только мешали, потому я немного подогнал его под свои потребности, поудаляв то, что мне было не нужно.
Со временем файл разрастался, лишнее из нормалайза удалялось, недостающее добавлялось.
Основной целью его создания было максимально подготовить основу для любого проэкта, что по-моему получилось, даже очень удачно. Файл получился довольно универсальный, но все же перед подготовкой проэкта в него нужно заглядывать и возможно что-то коректировать.
Надеюсь вы подчеркнете для себя что-то полезное, здесь вы можете ознакомиться с ним.
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 {
...
}
}
Нормальные дизайнеры всегда прорисовывают состояние фокуса.
Три основных состояния должны всегда присутствовать на каждом интерактивном элементе (: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;
}
Часто встречал, что эти семантические элементы форм использовались в декоратиыных целях.
Для такого:
Никогда так не делайте, это пример худшей практики. Вот пару примров с нормальной реализацией:
(Тег 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 в % для псевдоэлемента обертки (:before). Как известно padding в % берет значение ширины родителя, не зависимо заданы вертикальные или горизонтальные значения.
(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
Так почему не ресет или не нормалайз? Они не могут полноценно подготовить проект, в любом случае приходится немало дописывать, и потому практически у каждого верстальщика есть свои наработки.
Спасибо, что прочитали мою статью, надеюсь она будет вам полезна. Вопросы и предложения, идеи и замечания приветствуются.
P. S. Советую ознакомиться с публикацией Организация отступов в верстке (margin/padding). И советую использовать css линтеры. И кому интересно, может решить css задачку.
Автор: yurch-html