Оптимизация css своими силами
Содержание:
- Update: статистика по сжатию jQuery.js
- Как не ошибиться с z-index?
- Использовать кэш браузера для ускорения
- Помещайте таблицы стилей вверху страницы
- Делайте Ajax-элементы кэшируемыми
- Сжатие CSS с помощью онлайн компрессоров
- CSS Properties
- Сжать фотографии, иллюстрации и другую графику
- Сброс стилей
- Объявление первой переменной CSS
- Когда применять высоту/ширину в 100%?
- min(), max()
Update: статистика по сжатию jQuery.js
Версия jQuery: 1.3.2. Это для примера, с тем же успехом можно было взять и другую ветку.
В названии файлов
- min — родная минификация jQuery. Тот же результат получается при минификации yui compressor 2.4.2
- packer — означает, что применили PHP packer 1.1
- gz — обычный gzip. Таким же gzipом сжимает скрипты вебсервер.
Несколько суффиксов обозначают два последовательно запущенных компрессии. Например, .min + .gz означает минифицированный и затем gzip’ованный скрипт.
Почти все современные браузеры принимают от сервера gzip’ованные скрипты.
jquery-1.3.2.js | 120763 |
jquery-1.3.2.js.gz | 35361 |
jquery-1.3.2.min.js | 57254 |
jquery-1.3.2.min.js.gz | 19716 |
jquery-1.3.2.pack.js | 41025 |
jquery-1.3.2.pack.js.gz | 20274 |
Из таблицы видно, что наилучший результат достигается после минификации с последующим gzip (jquery-1.3.2.min.js.gz).
Итак, лучший метод сжатия выбран как в теории и проверен на практике. Это минификация скрипта. А gzip пусть делает сервер.
Как не ошибиться с z-index?
Все элементы на странице позиционируются в трехмерном пространстве: в дополнение к вертикальному и горизонтальному позиционированию, элементы также располагаются вдоль оси Z. На первый взгляд, эта концепция кажется довольно простой: элементы с более высоким z-index отображаются поверх элементов с более низким z-index.
К сожалению, вещи могут быть более сложными, чем они кажутся на первый взгляд. Я вообще уверен, что это самое запутанное CSS-свойство. Уверен, что проблемы с z-index — самые распространенные и раздражающие, с которыми только можно встретиться во время работы с CSS. Но мы постараемся найти решение.
Начнем с начала: свойство z-index не работает со статичными элементами. Для того, чтобы сдвинуть элемент по оси Z, нужно определить позиционирование для элемента, как relative, absolute или fixed. Так что первая вещь, которую мы должны сделать — убедиться, что элемент правильно спозиционирован, прежде чем вообще задумываться о том, чтобы назначить ему z-index.
Теперь, следует запомнить, что элементы в DOM не располагаются на одном и том же слое. Это означает, что выставления z-index в очень большое значение может быть недостаточно для того, чтобы отобразить его поверх других элементов. Это называется контекстом наложения.
Меняя положение по оси Z, элементы можно заставить перекрывать друг друга в нужном порядке. Вот как, согласно отображаются элементы в рамках одного группового контекста:
- фон и границы элемента, который формирует групповой контекст
- дочерние групповые контексты с отрицательными уровнями (первыми идут наименьшие)
- внутри-потоковые, не-строчные, неспозиционированные потомки
- не-спозиционированные плавающие элементы
- внутри-потоковые, строчные, неспозиционированные потомки, включая таблицы и большинство строчных блоков
- дочерние групповые контексты с уровнем 0 и спозиционированные потомки с уровнем 0
- дочерние групповые контексты с положительными уровнями (от меньшего к большему)
Когда результат ужасает
Хорошо, это была самая основная информация о свойстве z-index. Знания об этом могут сэкономить вам много времени, и уменьшить количество проблем, уж будьте уверены. К сожалению, этого недостаточно. Это были ещё цветочки!
Дело в том, что каждый групповой контекст имеет свой собственный масштаб по оси Z. В основном, элемент A в групповом контексте 1 и элемент B в групповом контексте 2 не могут взаимодействовать посредством z-индексов. Это значит, что элемент A является частью группового контекста, который находится в самом низу порядка группировки, и нет возможности вывести его перед элементом B, который находится в другом групповом контексте, который имеет более высокий групповой порядок, даже если вы зададите ему очень высокий z-index.
Но подождите — на самом деле, все еще хуже. Элемент html формирует корневой групповой контекст. В таком случае, каждый спозиционированный (не-статичный) блок со значением z-index больше, чем auto создает новый групповой контекст. Ничего нового в этом нет. А вот здесь все становится довольно печально: некоторые CSS-свойства, совершенно не связанные с позиционировнием, создают новые групповые контексты. К примеру, opacity.
Да, да — свойство opacity создает новый групповой контекст. Так же действуют свойства transform и perspevtive. Но ведь это не имеет смысла, не так ли? Значит, что если у вас есть элемент с прозрачностью, отличающейся от 1, или с трансформацией, отличной от none — у вас есть потенциальная проблема.
К сожалению, каждая проблема с z-index уникальна, так что нет возможности предложить какое-либо универсально решение для всех проблем с z-index. Под конец можно вывести несколько заключений:
- всегда проверяйте, что вашим элементам задано позиционирование, прежде чем применять к ним z-index
- не используйте z-index с большими значениями, это абсолютно бессмысленно. В большинстве случаем вполне достаточно z-index: 10
- убедитесь, что элементы, которым вы хотите изменить порядок отображения, принадлежат одному групповому контексту
- если у вас до сих пор не решилась проблема, убедитесь, что у вас на пути нет трансформированных или полупрозрачных элементов
Использовать кэш браузера для ускорения
Ускорить загрузку страницы помогает кэширование в браузере пользователя. При первой загрузке страницы файлы помещаются в кэш браузера с меткой времени, а при повторных посещениях они загружаются из кэша, а не с хостинга. Когда указанный промежуток времени пройдет, файлы обновятся с хостинга. Для кэширования подойдут файлы, которые изменяются не постоянно, иначе пользователь не увидит важных изменений. Статические объекты можно кэшировать от года и дольше.
Google рекомендует настроить сервер так, чтобы он возвращал ответ с HTTP-заголовком Cache-Control, например:
Cache-Control: max-age=31536000
Директива «max-age» указывает, как долго браузер должен кэшировать ресурс в секундах. Значение 31536000 соответствует году: 60 секунд * 60 минут * 24 часа * 365 дней = 31536000 секунд.
Google советует применять «no-cache» для объектов, которые могут обновляться: тогда браузер по-прежнему будет кэшировать ресурс со значением «no-cache», но сначала проверит актуальность на сервере.
Кэширование для Nginx
Для сервера Nginx подходит модуль expires в файле конфигурации. Нужно перечислить форматы файлов для кэширования и указать время хранения кэша:
location ~* \.(js|css|png|jpg|jpeg|gif)$ { expires 86400s; log_not_found off; }
Время можно указать в любом формате: секунды — s, часы — h, дни — d и месяцы — m, обозначение «max» указывает на кэширование навсегда.
Вместо времени хранения файла можно указать дату следующего обновления файла в кэше:
expires Fri, 24 Nov 2017 01:01:01 GMT;
Строка log_not_found off нужна для снижения нагрузки на сервер, она отключает ведение лога сообщений с ошибкой 404 для перечисленных файлов.
Метод Cache-Control
Метод позволяет указать для кэширования файлы конкретных форматов. В файле .htaccess в конструкции FilesMatch нужно указать расширения файлов для кэширования и время сохранения файла в кэше в секундах:
# 1 Month for most static assets <filesmatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$"=""> Header set Cache-Control "max-age=2592000" </filesmatch>
С помощью другого кода можно запретить кэшировать какие-то отдельные файлы по форматам, обычно это используют для динамических файлов. Для этого в файл .htaccess нужно вставить заголовок и форматы файлов, кэширование которых запрещено:
<filesmatch ".(pl|php|cgi|spl|scgi|fcgi)$"=""> Header unset Cache-Control </filesmatch>
Кэширование по времени
Другой способ — расписать отдельно разное время сохранения в кэш для разных форматов. Для этого нужно добавить код с директивами в начало файла .htaccess, указать, какие файлы сохранять в кэш и как долго:
## EXPIRES CACHING ## <ifmodule mod_expires.c=""> ExpiresActive On ExpiresByType image/jpg "access 1 year" ExpiresByType image/jpeg "access 1 year" ExpiresByType image/gif "access 1 year" ExpiresByType image/png "access 1 year" ExpiresByType text/css "access 1 month" ExpiresByType text/html "access 1 month" ExpiresByType application/pdf "access 1 month" ExpiresByType text/x-javascript "access 1 month" ExpiresByType application/x-shockwave-flash "access 1 month" ExpiresByType image/x-icon "access 1 year" ExpiresDefault "access 1 month" </ifmodule> ## EXPIRES CACHING ##
Внимательно подойдите к выбору сроков хранения контента, определите временные промежутки, которые подойдут файлам. Если вы планируете изменять какие-то элементы, а в кэш указали долгий срок хранения, то пользователь не увидит обновления, если не будет чистить кэш браузера.
После сохранения нужно обновить страницу.
Проверить кэширование в Google Chrome можно с помощью веб-инспектора Chrome DevTools. Столбец Size в Chrome DevTools поможет убедиться, что ресурс в кэше:
Столбец Size в Chrome DevTool. Источник —
Вкладка Headers покажет, как установлен Cache-Control:
Проверка заголовка Cache-Control. Источник — Google
Помещайте таблицы стилей вверху страницы
Исследуя производительность Yahoo!, мы обнаружили, что перемещение таблиц стилей в заголовок (HEAD) приводит к ускорению загрузки страниц. Дело в том, что в этом случае страница формируется последовательно.
Инженеры интерфейса, заботящиеся о производительности, желают именно этого; то есть хочется, чтобы браузер мог отобразить всё содержимое как можно быстрее
Это особенно важно для больших страниц, которые просматривают пользователи с медленным соединением. Важность предоставления пользователям визуальной обратной связи, например, индикатора загрузки, хорошо изучена и документирована
В нашем случае страница и является этим индикатором! Когда браузер загружает страницу последовательно: заголовок, панель навигации, логотип и т.п. — все компоненты служат индикаторами для ожидающего посетителя.
При расположении таблиц стилей внизу документа становится невозможной последовательная формирование во многих браузерах, включая Internet Explorer. Они откладывают формирование, чтобы избежать переотображение элементов страницы, если их стиль изменится. Пользователю приходится ждать и смотреть на пустой белый экран. Firefox не блокирует визуализацию, таком образом, когда стили загружены, некоторые элементы будут изменены, что приведёт к появлению моментов, когда страница .
В четко сказано, что стилевые таблицы должны быть расположены в заголовке страницы: «Unlike A, may only appear in the HEAD section of a document, although it may appear any number of times.» Ни одна из альтернатив: пустой белый экран или момент нестилизованного текста — не стоят риска. Оптимальное решение — следование HTML-спецификации.
Делайте Ajax-элементы кэшируемыми
Люди спрашивают, применимы ли эти правила улучшения эффективности к приложениям Web 2.0. Конечно! Это правило было первым, которое принесло плоды после начала работы приложений Web 2.0 на Yahoo!.
Чтобы улучшить производительность, важно оптимизировать эти ответы. Основной способ добиться хорошей производительности Ajax — кэширование, как описано в
Некоторые другие правила также применимы к Ajax:
Однако, правило 3 является основным для разгона приложения. Посмотрим пример. Почтовый клиент на технологии Web 2.0 может использовать Ajax, чтобы загрузить адресную книгу пользователя для автопродолжения. Если пользователь не изменял её с прошлой загрузки, то адресную книгу можно взять из кэша, если прошлый ответ Ajax был кэшируемым с использованием заголовка Expires. Браузер должен знать, когда использовать ранее кэшированную адресную книгу, а когда загрузить с сервера новую. Это можно сделать, добавив временнУю отметку к URL книги, например, . Если она не изменялась с момента последней загрузки, то отметка будет той же самой и адресная книга будет взята из кэша браузера. Если же пользователь изменил адресную книгу, то отметка времени модификации не совпадёт с той, что соответствует кэшу и браузер запросит обновлённые данные.
Сжатие CSS с помощью онлайн компрессоров
Анализируя работу cssкомпрессоров, можно сделать следующие выводы о степени сжатия css. Эксперимент проводился на основании двух css файлов со следующими параметрами:
первый – 7 372 байт
второй – 62 609 байт
Первый css написан коротко и читабельно, поэтому сжиматься он будет хуже.
Онлайн компрессор CleanCSS
Адрес: www.cleancss.com
Довольно таки солидный сервис, давайте посмотрим результаты его сжатия css.
Результат:
первый – сжат до 7 075 байт (96 %)
второй – сжат до 52 797 байт (84,3 %)
Онлайн компрессор FormatCSS
Адрес: www.lonniebest.com/FormatCSS
Этот сервис предназначен более для форматирования css файлов, нежели для их сжатия. Текст css вводится с помощью скопировать/вставить.
Результат:
первый – сжат до 8 105 байт (109,9 %)
второй – сжат до 61 715 байт (98,5 %)
Онлайн компрессор Robson CSS Compressor
Адрес: iceyboard.no-ip.org/projects/css_compressor
Сервис гибкий в плане загрузки исходного кода css. В него можно загрузить css из локального каталога, из интернета или копировать/вставить. Давайте посмотрим на результаты сжатия css файлов.
Результат:
первый – сжат до 6 326 байт (86,3 %)
второй – сжат до 48 985 байт (78,2 %)
Онлайн css html компрессор Tabifier
Адрес: tools.arantius.com/tabifier
Позволяет сжимать не только css, но и html код. Но результат не очень впечатляет, делайте выводы сами.
Результат:
первый – сжат до 7 876 байт (106,8 %)
второй – сжат до 60 706 байт (96,9 %)
CSS Properties
align-contentalign-itemsalign-selfallanimationanimation-delayanimation-directionanimation-durationanimation-fill-modeanimation-iteration-countanimation-nameanimation-play-stateanimation-timing-functionbackface-visibilitybackgroundbackground-attachmentbackground-blend-modebackground-clipbackground-colorbackground-imagebackground-originbackground-positionbackground-repeatbackground-sizeborderborder-bottomborder-bottom-colorborder-bottom-left-radiusborder-bottom-right-radiusborder-bottom-styleborder-bottom-widthborder-collapseborder-colorborder-imageborder-image-outsetborder-image-repeatborder-image-sliceborder-image-sourceborder-image-widthborder-leftborder-left-colorborder-left-styleborder-left-widthborder-radiusborder-rightborder-right-colorborder-right-styleborder-right-widthborder-spacingborder-styleborder-topborder-top-colorborder-top-left-radiusborder-top-right-radiusborder-top-styleborder-top-widthborder-widthbottombox-decoration-breakbox-shadowbox-sizingcaption-sidecaret-color@charsetclearclipcolorcolumn-countcolumn-fillcolumn-gapcolumn-rulecolumn-rule-colorcolumn-rule-stylecolumn-rule-widthcolumn-spancolumn-widthcolumnscontentcounter-incrementcounter-resetcursordirectiondisplayempty-cellsfilterflexflex-basisflex-directionflex-flowflex-growflex-shrinkflex-wrapfloatfont@font-facefont-familyfont-kerningfont-sizefont-size-adjustfont-stretchfont-stylefont-variantfont-weightgridgrid-areagrid-auto-columnsgrid-auto-flowgrid-auto-rowsgrid-columngrid-column-endgrid-column-gapgrid-column-startgrid-gapgrid-rowgrid-row-endgrid-row-gapgrid-row-startgrid-templategrid-template-areasgrid-template-columnsgrid-template-rowshanging-punctuationheighthyphens@importisolationjustify-content@keyframesleftletter-spacingline-heightlist-stylelist-style-imagelist-style-positionlist-style-typemarginmargin-bottommargin-leftmargin-rightmargin-topmax-heightmax-width@mediamin-heightmin-widthobject-fitopacityorderoutlineoutline-coloroutline-offsetoutline-styleoutline-widthoverflowoverflow-xoverflow-ypaddingpadding-bottompadding-leftpadding-rightpadding-toppage-break-afterpage-break-beforepage-break-insideperspectiveperspective-originpointer-eventspositionquotesresizerighttab-sizetable-layouttext-aligntext-align-lasttext-decorationtext-decoration-colortext-decoration-linetext-decoration-styletext-indenttext-justifytext-overflowtext-shadowtext-transformtoptransformtransform-origintransform-styletransitiontransition-delaytransition-durationtransition-propertytransition-timing-functionunicode-bidiuser-selectvertical-alignvisibilitywhite-spacewidthword-breakword-spacingword-wrapz-index
Сжать фотографии, иллюстрации и другую графику
На сайтах часто используют много больших графических элементов в хорошем качестве — фотографии в высоком разрешении, баннеры, иллюстрации. Если они много весят, то тормозят загрузку страницы, поэтому их нужно сжать
Даже если для просмотра принципиально важно хорошее качество и большой размер фотографий, есть способы сжимать изображения без визуальных потерь.
Как оптимизировать картинки для сайта:
-
Подберите разрешение.
Незачем загружать изображение в большом разрешении, если оно будет отображаться в маленьком без увеличения по клику. -
Подберите формат.
JPEG подходит для фотографий, PNG для дизайнерской графики, SVG для вектора. Google также индексирует формат WebP, который весит меньше, но не все браузеры его поддерживают. Яндекс не индексирует SVG и изображения в скриптах. -
Уменьшайте количество цветов.
Изображения, где нет сложных градиентов, требуют меньшего количества цветов. Можно оптимизировать картинку без потери качества, выбрав палитру меньше, тогда изображение будет хранить меньшее количество битов на пиксель.Слева направо: 32 бита (16M цветов), 7 бит (128 цветов), 5 бит (32 цвета)
Пропишите параметры в CSS.
Укажите размеры в коде или в редакторе изображений CMS. Для разных экранов и дисплеев с матрицей Retina нужны дополнительные варианты изображения разных размеров, чтобы браузер загружал нужное для устройства.
Используйте шрифты.
Если вы еще используете графику вместо шрифтов для текста, замените надписи на шрифты, это удобнее и меньше весит. Такой текст можно скопировать, поменять, масштабировать в любой момент.
Удалите лишние изображения.
Неинформативные картинки, иллюстрации ради разбивки текста и непонятные схемы лучше заменить на качественные изображения, которые помогут понять тему материала, или вообще удалить, чтобы они не прибавляли вес странице.
Минифицируйте.
Удаляйте XML-разметку с лишними метаданными, она появляется при работе с картинками в некоторых графических приложениях. EXIF — информацию о геоданных, дате съемки, фотокамере тоже можно удалить.
Используйте алгоритмы сжатия.
Настройте на сервере gzip-сжатие для SVG-графики.
Инструменты и сервисы для оптимизации изображений на сайте:
- CompressJPEGСервис для сжатия JPEG и PNG без потерь качества.
-
PunyPNG
Инструмент сжимает PNG, JPEG и GIF. - TinyPNGИнструмент для оптимизации изображений в PNG и JPEG.
- JpegtranИнструмент для оптимизации JPEG-изображений.
- OptipngИнструмент для оптимизации PNG без потерь.
- PngquantИнструмент сжимает PNG-изображения.
Вес HTML-страницы — один из факторов влияния на скорость ее загрузки у пользователей, поэтому ускорить загрузку можно, если облегчить вес страницы. Для этого рекомендуем сжать и сократить код, сжать изображения и избавиться от лишних элементов — неинформативных картинок, тяжелых анимаций и флеша.
Сброс стилей
Хорошо использовать немного улучшенную версию Meyers reset. Несколько аспектов удалены из reset’а, например списки иконок и элементов, которые могут привести к тому, что начнут объединяться вещи одинаковые по представлению, но разные по происхождению. Также в этой версии отсутствует установка в на 1, ведь всё зависит от шрифта и впоследствии могут возникнуть непредвиденные ошибки. В этом reset’е есть вещи, упомянутые выше. В CSS не добавляется атомарный класс , потому что есть лучшее решение, которое будет работать, даже если CSS не подгрузится, — hidden-атрибут. Обычно на скрытые элементы браузер выставляет , но это тоже можно изменить.
Исходники reset’a — https://github.com/NickGard/css-utils/blob/master/reset.css.
Ещё одна полезная штука — это класс . Вместе с для невидимого читаемого с экрана текста нужно использовать следующий блок кода:
Объявление первой переменной CSS
Чтобы объявить переменную, вам сначала нужно решить, в какой области должна быть переменная. Если вы хотите, чтобы она была доступна глобально, просто определите её в псевдоклассе , который соответствует корневому элементу в дереве документов (обычно это тег ).
Поскольку переменные наследуются, следующий ниже код делает вашу переменную доступной во всём вашем приложении, так как все ваши DOM-элементы являются потомками тега .
:root { --main-color: #ff6f69;}
Как вы можете видеть, вы объявляете переменную точно так же, как вы бы установили любое свойство CSS. Однако переменная должна начинаться с двух дефисов ().
Для получения доступа к переменной, вам нужно использовать функцию и передать имя переменной в качестве первого параметра.
#title { color: var(--main-color);}
И это назначит вашему заголовку цвет :
Функция поддерживает второй параметр, фолбэк, то есть значение (или также CSS-переменная), которое будет использоваться, если переменная, переданная первым параметром, не определена, например:
#title { color: var(--main-color, black);}
Если переменная недоступна, то будет использоваться черный цвет ().
Когда применять высоту/ширину в 100%?
Высота в 100%
Давайте сперва разберемся с менее сложным примером. Когда использовать height: 100%? Вообще-то многие из нас как минимум единожды задавались вопросом “какого черта? Я рассчитывал на то, что моя страница будет как минимум занимать всю высоту экрана!” Я прав?
Для того, чтобы ответить на этот вопрос, необходимо понимать, что на самом деле означает свойство height: 100%: полную высоту родительского элемента. Это далеко не означает “всю высоту экрана”. Так что если вы хотите, чтобы ваш контейнер занимал всю высоту экрана, height: 100% недостаточно.
Почему? Потому, что родительский элемент вашего контейнера (body) имеет высоту по умолчанию auto, что означает, что его размер определяется содержимым. Так что можете попробовать проставить height: 100% и для элемента body — это все равно не даст желаемого эффекта.
Почему? Потому, что родительский элемент тега body (html) имеет высоту по умолчанию auto, что означает, что его размеры зависят от содержимого. А что если попробовать задать элементу html height: 100%? Работает!
Почему? На самом деле потому, что корневой элемент (html) — это не самый последний родительский блок на странице — есть еще окно просмотра (viewport). Проще говоря — это окно браузера. Так что если задать height: 100% элементу html, вы сделаете его высоту, равной высоте браузера. Вот так-то просто.
Результат нашей истории отражен в следующем коде:
html, body, .container { height: 100%; }
А что если у родительского элемента задан min-height, но не задан height?
Roger Johansson недавно выявил проблему с height: 100% в случае когда у родительского элемента нет назначенной высоты, но для него задана минимальная высота. Я не буду углубляться в описание, но в итоге решение состоит в том, что родительскому элементу нужно задать высоту в 1px, так чтобы дочерний элемент мог растянуть его до min-height.
.parent { min-height: 300px; height: 1px; /* Необходим для того, чтобы дочерний элемент раскрылся на всю высоту min-height */ } .child { height: 100%; }
Ширина в 100%
Теперь давайте разберемся с параметром width: 100%. Сразу напомню, что, как и с высотой, настройка width: 100% — это указание, что элемент должен быть такой же ширины, как и родительский элемент. Никаких сюрпризов здесь нет.
А сейчас поделюсь небольшим секретом. Ширина — не совсем правильное название для этого свойства. Свойство width на самом деле не определяет всю ширину элемента, а только ширину его содержимого, что совершенно отличается от полной ширины элемента.
Если мы добавим внутреннее поле и границы к вашему элементу, которому выставлена ширина width: 100%, то этот элемент уже не будет вписываться в родительский — он будет выходить за его пределы. Все это из-за полей и границ. И именно поэтому свойство width должно было бы называться content-width (шириной контента). Пожалуйста, рассмотрите следующий пример, чтобы понять, что я имею в виду:
Ширина родительского элемента равна 25em. Ширина дочернего элемента равна 100% (от его родительского элемента), но также имеет поля размером 1em (1em слева, 1em справа. В сумме по горизонтали это будет 2em), а также границу в 0.5em (всего 1em по горизонтали), что приводит к тому, что результирующая ширина дочернего элемента состовит 25em(100%) + 2em + 1em = 28em. Хмм… Хьюстон, похоже, у нас проблема.
Есть четыре способа поправить положение дел. Первый, и определенно лучший — избегать установки width: 100%, особенно если в этом нет пользы, как в данном случае. Дочерний элемент является блочным элементом, что автоматически расширяет его до ширины родительского элемента (без той проблемы, что мы видим выше). К сожалению, если мы имеем дело со строчно-блочными элементами, то можно воспользоваться следующим фиксом.
Можно не использовать width: 100%, и выставить конкретную ширину элементу самостоятельно. В нашем случае, это 20 — (2 + 1) = 22em. Надо сказать, что это решение плоховато, так как нужно вручную вычислять необходимую ширину элемента. Поищим другой способ!
Третьим вариантом будет использование calc(), чтобы автоматизировать вычисления: width: calc(100% — 3em). Все равно плохо. Во-первых, нам нужно вычислять сумму горизонтальных полей + вертикальных границ. Во-вторых, calc() поддерживается не самым лучшим образом в браузерах (его не поддерживают IE 8, Safari 5, Opera 12 и стандартный браузер Android).
Четвертый вариант — использовать свойство box-sizing: border-box. По существу, она меняет поведение модели контейнера так, что свойство width отражает суммарную ширину элемента, границы и поля включены. Хорошие новости заключаются в том, что поддержка браузерами этого свойства довольно хороша (все, кроме IE 7- и Opera 9).
min(), max()
Функция возвращает минимальное из переданных значений, — максимальное. При использовании процентов или выбираемое значение будет динамическим и будет зависеть от внешних условий. Например:
Если поресайзить окно с примером, можно увидеть как это работает.
Если вычисленное значение для меньше , ширина блока будет равна . Как только станет больше , функция выберет меньшее значение, то есть , и дальше блок тянуться не будет.
Функция будет выбирать подходящее значение учитывая ширину окна в данный момент.
Этот код не делает ничего особенного, что не умел бы CSS без математических функций: точно такое же поведение можно получить задав и :
Оба варианта для сравнения:
Порастягивайте демо, чтобы увидеть, что разницы в поведении блоков нет.
На первый взгляд, и не делают ничего интересного, но если подумать, как много мест в CSS, где можно управлять диапазоном значений?
Это доступно только для ширины и высоты:
- , ,
- , ,
и их аналогов, привязанных к направлению письма:
- , ,
- , ,
У нас нет, например, или , но благодаря математическим функциям, можно добавить умную динамику практически в любое значение. Например, в размер шрифта:
Поресайзите демо, и вы увидите, что при растягивании шрифт будет бесконечно расти, но при сужении, как только станет меньше или равным , размер шрифта застынет на этом значении.
Если попытаться реализовать подобное на JS, пришлось бы отслеживать ресайз окна, получать вычисленное значение, и при превышении заданного порога, фиксировать значение на определённом уровне. При использовании и браузер всё делает сам: отслеживает изменение значений и, при необходимости, фиксирует их — нам нужно просто выбрать функцию и задать диапазон значений.
Это будет работать во всех свойствах, которые используют размеры, в том числе в тенях, градиентах и прочем. Пример с :
Размер тени будет зависеть от размера окна браузера, минимальное значение — .
Экспериментируя с функциями и можно заметить, что они дают возможность управлять или минимальным значением, или максимальным, но нельзя контролировать и то, и другое одновременно. Хотя совершенно логичным выглядит желание, например, задать размер шрифта, который будет расти в диапазоне от минимального значения до максимального и не выходить за эти значения.
Для такого есть ещё одна функция: