Советы по CSS, которые вы вряд ли найдете в самоучителях

https://medium.freecodecamp.org/css-tips-that-you-likely-wont-see-in-any-tutorial-3af201315a76
  • Перевод
Существуют определенные правила CSS, которые можно найти в любом учебнике. Но есть также правила CSS, которые вы не найдете в пособиях, но столкнетесь с ними, как только начнете писать код. Я уверен, вы уже разобрались в том, как выровнять элемент по вертикали или создать сложный макет. Мы не будем об этом говорить.

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



Ниже изложено то, чему руководства по CSS меня не научили.

Свойство padding-top относительно ширины родительского элемента


Как часто вы использовали относительные единицы в CSS? Я их большой поклонник, потому что они позволяют создать адаптивный веб-сайт, не слишком углубляясь в медиазапросы. Если вы хотите установить высоту элемента в половину от высоты родителя, то достаточно просто написать height: 50%.

Вы можете использовать относительные единицы где угодно. Если хотите добавить расстояние между двумя вертикальными элементами, то можете написать margin-top: 15% и появится внешний отступ. Расстояние будет составлять 15% от исходной высоты. Я думаю, вы все это знаете, и не буду тратить ваше время. Но, возможно, вы не знаете, что все не так просто.

В некоторых ситуациях лучше использовать padding вместо margin. Но когда вы устанавливаете padding-top: 15%… Что за?..

Свойство не работает так, как мы ожидаем. Оно не устанавливает параметры относительно высоты родителя. Что происходит?

Объяснение


Оно устанавливает параметры относительно родительской ширины. Вам нужна демонстрация? Вот:


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

Нет, я шучу — нет никаких объяснений, почему так происходит. По крайней мере, я нигде не смог найти объяснений. Просто так происходит, имейте это в виду.

Хотя мы и не понимаем, почему разработчики сделали так, но можем использовать эту особенность в наших интересах. Для нашего элемента мы устанавливаем следующее:

.parent {
  height: auto;
  width: 100px;
}

.child {
  padding-top: 100%;
}

Тогда высота элемента будет такой же, как высота дочернего элемента, хотя мы задали height: auto. С другой стороны, высота дочернего элемента будет такой же, как и ширина родительского элемента, поскольку мы устанавливаем padding-top: 100%. В результате получается квадрат, и элемент будет поддерживать это соотношение при любых размерах.

Вот рабочий пример:


Если измените padding-top: 100% на любой другой процент, то получится прямоугольник. Если меняете ширину, то соотношение все равно сохраняется.

Трансформация может накапливать правила


Если вы изучали информатику, то наверняка помните эту ужасную черепаху и ее двигающуюся ручку. Эта образовательная концепция более известна как черепашья графика, цель которой состоит в том, чтобы провести черепаху по пути при помощи простых инструкций — «20 шагов вперед», «поворот на 90 градусов» и тому подобное.

Что, если бы используя CSS, вы могли задать команду перемещение на «20 пикселей вправо» относительно текущего положения элемента, а не его стартовой позиции? А если я скажу, что вы можете это сделать, используя свойство transform?

Многие разработчики не знают, что свойство transform может накапливать правила и правило n+1 будет относиться к позиции, достигнутой в n-м правиле, а не к исходной позиции.

Вы растеряны? Возможно, этот пример поможет вам прийти в себя:


Обратите внимание, что мы не использовали никаких переменных JavaScript для сохранения текущей позиции или текущего вращения. Эта информация нигде не хранится! Решение простое, если напишете:

transform: translateX(20px);

А затем добавите следующее правило:

transform: translateX(20px) translateX(40px)

Второе правило не будет заменять первое — они будут применяться последовательно. Тот факт, что они применяются последовательно имеет важное значение. Когда вы поворачиваете элемент, вы изменяете систему отсчета, и дальнейшие правила будут относиться к новой системе отсчета. Таким образом, эта запись:

transform: rotateZ(20deg) translateX(30px)

будет отличаться от такой:

transform: translateX(30px) rotateZ(20deg)

Вы также можете комбинировать разные единицы измерения. Например, вы можете отцентрировать элемент размером в 600 следующим образом:

transform: translateX(50vw) translateX(-300px)

Но если вы не собираетесь его анимировать, то, возможно, calc () — лучшая альтернатива.

Если вы волнуетесь по поводу черепахи, то я создал другой фрагмент, который воссоздает динамику:


К сожалению, она пока не рисует. Но, если захотите, всегда можете реализовать функцию рисования.

Внешние и внутренние отступы отсчитываются по часовой стрелке


Это легко и многие подумают, что я пишу банальные вещи, но я видел так много людей, борющихся с четверками, что перестал считать это само собой разумеющимся.

Многие разработчики не знают, что почти каждое свойство CSS имеет сокращенную альтернативу. Другие разработчики знают это, но продолжают использовать полные версии, потому что никогда не помнят порядок.

Позвольте дать вам подсказку:
Отступы и границы следуют по часовой стрелке

Объясню проще. Вы с уверенностью можете использовать:

padding-top: 3px;
padding-left: 6px;
padding-right: 6px;
padding-bottom: 3px;

Но точно так же вы можете использовать более короткую альтернативу:

padding: 3px 6px 3px 6px;

Порядок запомнить легко — просто посмотрите на эти часы:



Начинайте с 12:00 и продолжайте движение по часовой стрелке. Вы получите правильный порядок.

Если вместо этого вы используете только два значения:

padding: 2px 4px;

Браузер расширит его, повторив параметры:

padding: 2px 4px 2px 4px;

Если вы используете три значения:

padding: 2px 4px 6px;

Браузер будет использовать среднее значение как для левого, так и для правого края, как если бы вы написали:

padding: 2px 4px 6px 4px;

Фон поддерживает несколько изображений


Это одно из наименее известных свойств, хотя оно широко поддерживается.

Вы знаете, что можно указать URL-адрес изображения внутри свойства background, но, если необходимо, можете вставить столько изображений, сколько хотите. Все, что вам нужно сделать, это разделить их запятой:

background: url('first-image.jpeg') top left,
            url('second-image.jpeg') bottom right;

Почему это может быть полезно? Что вы думаете о Линусе Торвальдсе на фоне сгенерированного при помощи CSS восхода солнца?


Вы также можете сделать квадратным прямоугольное изображение, добавляя те затененные границы, которые так популярны в Instagram. Для этого я повторил одно и то же изображение дважды, увеличив фоновое изображение в 5 раз:


Обнаружение сенсорных устройств


Благодаря медиа-запросам мы можем сделать сайты гибкими, а макеты адаптировать к экранам различных размеров. Но этого недостаточно!

Смартфоны, планшеты и классические персональные компьютеры отличаются по своей природе. Дело не в размере экрана.

На устройстве с сенсорным экраном вы используете экранные жесты, а такие инструменты, как HammerJS помогают в этом. С помощью мыши вы только кликаете, но с большей точностью. Если вы адаптировали свой сайт к экранам разных размеров, возможно, вы задумываетесь над его гибкостью в других направлениях и поддержкой различных типов ввода!

Вам не нужен сложный JavaScript-код для определения user-agent. Все необходимое есть в CSS:

@media (any-pointer: fine) {
  /*
    These rules will be applied to not-touchscreen devices
  */
}

@media (any-pointer: coarse) {
  /*
    These rules will be applied to touchscreen devices only
  */
}

Вот пример:


Подсказка: Для проверки вам не нужен смартфон, можете имитировать сенсорное устройство с помощью инструментов Google Chrome, просто щелкнув этот значок:



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

В конце концов, вы можете предусмотреть файл touchscreen.css и при необходимости его импортировать:

@import url('touchscreen.css') screen and (any-pointer: coarse);

Примечание: в настоящее время не поддерживается Firefox, как вы можете видеть на caniuse.com.

Отступы схлопываются



«И следите за лестницами. Они любят меняться» (Перси Уизли Гарри Поттеру)

Мне нравится CSS — это чистый, точный и элегантный язык, в нем есть все, что нужно разработчикам.

Вы применяете правило, и оно работает. Но когда я думал, что знаю все о CSS, произошло вот это:


Что, черт возьми, происходит? Вероятно, вы ждете, что текст будет внутри поля заголовка, но заголовок оказался внизу. Я не хотел подобного расклада. Позже я обнаружил, что с отступами происходит путаница.

Что это значит? Предположим, мы хотим создать такой макет:



Мы создали разметку для трех элементов и установили разную высоту верхней границы для каждого из них. Вроде бы все должно работать? Нет.

Если вы так сделаете, браузер заметит три смежных поля и захочет объединить их в один большой блок.

Результат будет выглядеть так:



Что случилось? Я не знаю. Это историческая особенность CSS. Я думаю, что когда CSS стандартизировался, поля вообще не являлись проблемой, а макеты не были такими сложными, как сейчас. Поэтому разработчики решили, что это полезная функция. Но сейчас она не имеет смысла.

Если вы работали с CSS много лет и никогда не встречались с этой проблемой, то это потому, что отступы объединяются только когда:

  • поля вертикальны (с горизонтальными подобного не происходит);
  • внешние элементы не содержат текст или другой контент;
  • не установлены внутренние отступы или границы;
  • свойство display определено как «block»;
  • свойство overflow отличается от «initial»;
  • отступы не являются отрицательными.

И список можно продолжить. Если вы столкнулись с этой проблемой, то можете просто исключить одно из этих условий (кроме первого), и отступы придут в норму. Вы также можете избегать использования margin-top, а вместо этого использовать top и padding-top.

Обратите внимание, что это может случиться и для элементов одного уровня. Если у вас есть два родственных элемента один над другим и вы устанавливаете margin-bottom: 30px для первого и margin-top: 60px для второго, то с наименьшим будут проблемы. Отступы в результате не будут равны 30 + 60 = 90 пикселей, а будут равны наибольшему значению (30, 60) = 60 пикселей.

Финальные размышления


На этом все! Надеюсь, я не зря тратил время на статью и она оказалась полезной для вас.


Заглядывайте на VPS.today — сайт для поиска виртуальных серверов. 1500 тарифов от 130 хостеров, удобный интерфейс и большое число критериев для поиска самого лучшего виртуального сервера.

Поиск VPS

62,00

Помогаем найти самый лучший виртуальный сервер

Поделиться публикацией
Комментарии 24
    +3
    Исправьте последовательность в:
    padding-top: 3px;
    padding-left: 6px;
    padding-right: 6px;
    padding-bottom: 3px;

    Не по «часам».

    И в данном случае лучше использовать не padding: 3px 6px 3px 6px;, а padding: 3px 6px . Разумеется, если стороны равнозначны

    Добавлю еще немного не в тему, для calc() на css-tricks есть еще интересное применение
      +2
      Объяснение
      Оно устанавливает параметры относительно родительской высоты.

      относительно родительской ширины

        +1
        Спасибо, исправлено.
        +3
        Как минимум половина советов описывается в начальных книгах.
          0
          Мне сейчас натаскивать на веб нового и эта статья в тему.
          +4
          Оно устанавливает параметры относительно родительской высоты. Вам нужна демонстрация?

          Не высоты, а ширины.

          Если вы так сделаете, браузер заметит три смежных поля и захочет объединить их в один большой блок.

          Результат будет выглядеть так:
          image

          Не совсем так. За отступ берется не сумма а максимальное значение из Margin 1, Margin 2 и Margin 3.

          Если вы работали с CSS много лет и никогда не встречались с этой проблемой, то это потому, что отступы объединяются только когда:
          • ...
          • свойство overflow отличается от «initial»;
          • ...


          Наоборот. Не отличается от initial, а равно initial. Или visible.
            0
            И если уж быть совсем точным, то padding-top считается не от ширины родителя, а от ширины доступного пространства. Т. е. если у родительского блока стоит box-sizing: border-box; и есть padding или border, то их размеры вычитаются из той ширины от которой считается padding-top и т. п.
              +1

              Нет. Если вы возьмёте один элемент из нескольких в ряду внутри флекс-контейнера (или гридов), то обнаружите, что размер будет считаться от ширины родителя, а не «доступного пространства», которое ещё было непонятно как считать, если пришлось бы учитывать такие вещи. Но да, эта ширина считается по content-box, то есть по внутренней стороне padding (все помнят блочную модель?), так же как и при стандартные объявления вроде width: 100%.

                0
                Спасибо. content-box это в моем понимании и есть «доступное пространство», просто не знал как его правильно обозвать.
            +2
            Или перевод так-себе, или автор так-себе. Много ошибок в статье.
              0
              Оно устанавливает параметры относительно родительской высоты

              Может все-таки ширины? И, кстати, почему только паддинг? Маргин в процентах тоже считается от ширины родительского контейнера
                0
                Про схлопывание конечно… нет приличных слов, сам по этим граблям ходил
                  0
                  «Трюк» с padding-top звучит как использование Undefined Behavior, особенно учитывая что в спецификации ничего про это нет (согласно данной статье). Я бы, в таком случае, воздержался от использования этого в проде, иначе есть риск нарваться на «багфикс», который добавит разъяснение в спецификации, и сделает
                  padding-top: x%
                  зависимым от высоты, а не ширины, во имя снижения количества неожиданностей в обработке.
                    +2

                    Всё там есть:


                    The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.

                    Даже подчёркивают, что рассчитывается относительно ширины даже для вертикальных паддингов.

                      0
                      Интересно, спасибо. Каюсь, сам спек не читал, рассуждал только по данному в статье на момент прочтения.
                        0

                        Вы просто немного не так поняли.


                        нет никаких объяснений, почему так происходит. По крайней мере, я нигде не смог найти объяснений.

                        Эта фраза не о том, что мы имеем дело с UB, а о том, что разработчики спецификации явно указали делать так, но не объяснили, почему. Впрочем, в спецификациях мотивацию и так обычно не указывают.

                          0
                          С моей колокольни исходная фраза выглядит как «поведение вот такое, но почему именно — я найти не сумел».
                          Что я воспринял как «официальная документация не включает объяснений такому поведению». Иными словами, в моей интерпретации звучит как UB, тогда как, по видимости (и в комментариях уже много раз сказано) поведение в точности соответствует спецификации (i.e. «почему» — «по спецификации»). Это, безусловно, ошибка трансляции с моей стороны, но теперь я убеждён, что автор статьи тоже причастен. Ещё раз спасибо.
                      0
                      В спецификации как раз и сказано от чего считается padding в процентах: https://www.w3.org/TR/CSS2/box.html#propdef-padding-top

                      Percentages: refer to width of containing block
                      0
                      интересно, что за руководства такие читал автор, что они его не научили таким базовым вещам… всё что тут описано будет новостью только для тех кто неделю назад не знал что такое css и есть в любой мало-мальски адекватной книжке или справочнике
                        0
                        Стараюсь всегда использовать такой вариант написания
                        padding-top: 0px;
                        padding-left: 0px;
                        padding-right: 0px;
                        padding-bottom: 0px;
                        Вариант, padding: 0 0 0 0; не столь интуитивно понятен. Хотя никогда не было проблем с написанием его.
                        Если с padding еще ладно, это не критично. То всякие бэкграунды и тп, пишу только отдельными свойствами. Я когда вижу правило записанное в одну строку, но при этом имеет длину книги война и мир, хочется лично разбить такому писателю.
                        Конечно имхо и на истину не претендую. Просто считаю, что читать правила так легче и понятней. А не когда сначала надо строку распарсить в уме, чтобы увидеть что там написано.
                          0
                          А каким инструментарием можно вообще развернуть краткий CSS в полный и наоборот? Чтобы копья не ломать.

                          Сокращают, вероятно, минификаторы…
                            0
                            Скорее всего копать в сторону css shortcat expanded плагинов для вашей IDE
                          0
                          Расчет вертикальных padding от ширины, а не от высоты вполне очевиден. Точнее понятно почему не сделали «по-правильному». Допустим, если бы он считал от высоты. Как можно посчитать процент от высоты, если рассчитанное значение снова влияет на высоту. Скажем высота блока 100px и мы поставили padding-top: 20%. При стандартной блочной модели высота блока должна была бы стать равной 120px, но тогда padding стал бы равным 24px (20% от 120px). Теперь получаем, что блок должен бы уже стать высотой 124px. И снова вызывает пересчет паддинга и так до бесконечности (на самом деле мы будем стремиться к какому то числу, но не достигать его)
                            0
                            Для меня года два назад фича с padding в %, который считается от ширины, стала откровением, я теперь использую ее постоянно, когда нужно выдержать соотношение сторон у блока при любых размерах экрана, к примеру, если мне надо блок 4:3, я делаю ему
                            padding-top: 75%, и вуаля, он будет иметь такое соотношения, только нужно понимать, что для родителя надо так же установить position: relative;, а для дочернего элемента position: absolute; top: 0; left: 0;, чтобы контент не убегал вниз на эти 75%

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

                            Самое читаемое