В этой статье Рейчел Эндрю рассматривает ситуации, в которых вы можете столкнуться с переполнением при верстке сайтов, и объясняет, как развивался CSS, чтобы создавать более эффективные методы разметки в ситуациях, когда объёмы контента заранее неизвестны
Примечание от переводившего
Большая просьба снисходительно отнестись к замеченным ошибкам в переводе, грамматике или пунктуации, и сообщить о них для исправления.
Спасибо
CSS был спроектирован, чтобы содержимое было удобочитаемым. Если вы рассматриваете HTML-документ, который размечен с помощью заголовков и параграфов (без применения CSS), он отображается в браузере в удобном для чтения виде. Заголовки большие и полужирные, а между параграфами остаётся пространство, которое контролируется таблицами стилей, встроенными в браузер. Однако, как только потребуется изменить макет страницы, вы начнете брать контроль над оформлением в свои руки. В некоторых ситуациях это будет значить, что вы берете на себя работу с переполнением элементов.
В этой статье я собираюсь рассмотреть разные ситуации, при которых мы можем столкнуться с переполнением в вебе. Мы увидим, как новые методы разметки и новые значения в CSS могут помочь нам справиться с переполнением и создавать менее хрупкий дизайн. Я также объясню одну из фундаментальных концепций, лежащих в основе проектирования на CSS — это предотвращение потери данных.
Что мы подразумеваем под переполнением?
Если вернуться на несколько лет назад (перед приходом таких методов разметки, как Flexbox и Grid), подумайте, как бы вы реализовали пример, отображенный ниже. Очень простой макет из трёх блоков, имеющих разное количество содержимого, но нижняя граница которых должна быть на одной линии.
С помощью float такая, казалось бы, простая задача была невозможна. Когда блок становится обтекаемым (float), он никак не взаимодействует с соседними; это значит, что нет возможности узнать, что следующий элемент выше и увеличить текущий до такой же высоты.
Иногда, пытаясь выстроить элементы по одной линии, разработчики задавали фиксированную высоту блоков, пытаясь предугадать количество возможного содержимого, чтобы сделать высоту одинаковой. Конечно, в вебе все не так просто и когда количество содержимого отличалось, или размер текста становился больше, текст начинал выходить за нижнюю грань блока. Это и было переполнение (overflow).
Иногда люди спрашивают, как они могут предотвратить попадание слишком большого количества содержимого на сайт. В техподдержку моей CMS обращались пользователи, которые спрашивали, как ограничить содержимое по этой самой причине. Они говорили, что этот дополнительный контент «ломает макет». Для тех из нас, кто понимал, что невозможность узнать высоту элементов было фундаментальной природой вёрстки, вынуждало создавать макеты, которые скрывали отсутствие равных по высоте блоков. Распространённым решением было добавление градиента с эффектом исчезновения контента, выходящего за границы. Мы бы избегали использования фоновых цветов и рамок для блоков. Или мы бы использовали техники создания искусственных колонок, чтобы сделать высоту элементов одинаковой.
Эта неспособность контролировать высоту одного элемента относительно других, следовательно, влияла на веб-дизайн — техническое ограничение изменяло способ проектирования сайтов. Я рада, что с появлением Flexbox и Grid эта проблема не просто исчезла, но и по умолчанию поведение этих новых методов разметки растягивают блоки на одинаковую высоту. Начальное значение свойства align-items - stretch, из-за которого блоки растягиваются на высоту Grid-области или Flex-контейнера.
Кроме того, CSS Grid дает нам хороший способ задавать элементам определенный размер, но позволять увеличиваться, если им это нужно. Если вы зададите размер трека (колонки или строки), используя функцию minmax(), сможете увидеть его минимальный и максимальный размер. Установка для строк значения minmax(200px, auto) означает, что трек всегда будет по крайней мере, 200px, даже если элементы сетки пусты. Однако, если содержимое grid-элемента больше 200px, благодаря значению auto этот элемент может расти. Вы можете увидеть это в примере ниже. Первая строка равна 200px, так как нет элементов, увеличивающих её. Во второе строке есть grid-элемент, содержимое которого не помещается и начинает работать значение auto, из-за чего строка становится больше 200px.
Функция minmax() дает вам возможность создавать интерфейсы так, будто они имеют идеальный фиксированный размер. В идеальном мире (когда количество содержимого соответствует ожиданиям), вы получите эти красивые одинаковые строки. Однако, если добавить дополнительный контент, не произойдет переполнения, как если бы вы задали фиксированную высоту строк в 200px. Строка будет расширяться; это может быть не совсем то, чего хотелось бы вам, как разработчику, но это не будет нечитаемым.
Строчное переполнение
Риск переполнения возникает всякий раз, когда мы ограничиваем размер элементов. В примере выше я описываю ограничение в измерении блока, которое пользователи с горизонтальным направлением языка будут воспринимать как высоту. Тем не менее, мы также можем получить переполнение, если ограничим ширину блока. Это то, что мы видим в меме «CSS is Awesome».
Теперь я немного лучшее понимаю концепцию переполнения, но в то время мой мозг просто взрывало непонимание того, почему кто-то подумал, что поведение по умолчанию должно просто выталкивать текст справа от блока, вместо того, чтобы сделать блок больше, как это всегда делали таблицы.
Так почему CSS выталкивает текст за рамки блока, вместо увеличения размера самого блока?
В меме получается переполнение в строчном направлении. Слово «awesome» больше, чем ширина, примененная к блоку, поэтому и переполняет его. CSS довольно разумно предполагает, что если вы задали блоку определённую ширину, вам нужен блок именно такой ширины. Возможно, он должен поместить в макет, который сломается, если блоки внезапно станут больше, чем было установлено.
Эта конкретная проблема (то есть, необходимость задавать размеры всем элементам макета и убеждаться, что в сумме они не превышают доступное пространство контейнера), — это та проблему, которую современные методы вёрстки решаются для нас. Если мы представим, что наш блок имеет такой специально подобранный размер, чтобы поместиться в строку с другими блоками в float-сетке, сегодня вместо этого вы можете выбрать использование Flexbox.
Используя float-макет, вы должны устанавливать размеры каждому элементу — возможно, до того, как вы узнаете какое у него будет содержимое. В этом случае вы можете столкнуться с тем, что большое содержимое будет находиться в маленьких контейнерах, а у небольшого содержимого останется лишнее пространство вокруг.
Однако, если мы используем Flexbox, мы можем позволить браузеру рассчитать, сколько пространства отдавать каждому элементу. Flexbox обеспечит более крупные элементы бОльшим пространством, а маленькие получат меньше. Это гибкое распределение размеров означает, что блок, который содержит слово «awesome» увеличится, чтобы вместить весь контент и текст не выйдет за его рамки. Проблема переполнения решена; такое поведение является именно тем, для чего Flexbox был создан. Flexbox отлично справляется с элементами разного размера и организует их в наиболее подходящий для них макет.
Вне Flexbox можно сказать, что наш блок должен быть настолько большим, насколько это нужно для контента и не более. Ключевое слово min-content может быть использовано как значение для свойства width или inline-size при работе с логическими свойствами, относящимися к потоку. Установите width: min-content и блок увеличится настолько, чтобы вместить слово «awesome».
Предотвращение потери данных
Причина, по которой блок переполняется (как в примере со словом, выходящим за границу блока) заключается в том, что у свойства overflow значением по умолчанию является visible. Вы можете (если захотите) управлять переполнением по-другому. Например, использование overflow: auto или overflow: scroll могло дать вашему блоку полосу прокрутки. Это, возможно, не то, чего бы вам хотелось в этой ситуации, но могут быть ситуации, когда блок с полосой прокрутки будет уместен.
Также можно было предположить, что вы готовы обрезать переполнение с помощью overflow: hidden. Возможно, вы могли подумать, что скрывать переполнения было бы лучше по умолчанию, однако, тот факт, что CSS выбрал делать переполнение по умолчанию видимым (а не скрытым), является ключом к основной ценности CSS-разработки. В CSS (как и во множестве других технологий), мы пытаемся избежать потери данных. Когда мы говорим про потерю данных в CSS, мы обычно говорим именно о части контента, которая станет не видна. В случае с overflow: hidden, контент, который переполняет родительский блок, исчезает. Это значит, что у нас нет способа добраться до него, чтобы узнать какую часть мы потеряли.
В определенных ситуациях это может быть серьезной проблемой. Если вы умудрились сделать вёрстку настолько хрупкой, что кнопка вашей формы вышла за пределы видимой области, у ваших пользователей не будет возможности отправить форму. Если последний абзац текста обрезан, мы никогда не узнаем, чем закончилась история. Также, проблема с исчезающими элементами заключается в том, что не всегда очевидно, что они пропали. Как разработчик, вы можете не заметить проблему, особенно если это происходит только при определенных размерах области просмотра в отзывчивом дизайне. Ваши пользователи могут не заметить проблему — они просто не увидят призыв к действию, или подумают, что проблема, по которой они не могут сделать заказ, в их устройстве и просто уйдут. Тем не менее, если элементы переполняются там, где не должны, вы, скорее всего, заметите это. Или, в худшем случае, кто-то, зашедший на сайт, заметит это и даст вам знать.
Именно поэтому в CSS элементы переполняются неаккуратно и достаточно заметно. Явно видя переполнение, вы с большей вероятностью исправите ошибку, чем если лишнее содержимое просто будет скрыто. Однако, с помощью свойства overflow вы получаете возможность самостоятельно принимать решение касательно того, что должно произойти. Если вы хотели бы, чтобы переполнение обрезалось (что может быть правильным решением в определенных ситуациях), используйте overflow: hidden.
Потеря данных и выравнивание
Лучшие инструменты выравнивания, которые мы получили за последние несколько лет, также могут приводить к потере данных. Рассмотрим колонку flex-элементов, которые находятся у края области просмотра и имеют разные размеры. При выравнивании значением flex-start, элементы выступают вправо. Однако, при выравнивании по центру значением center, более широкий элемент будет выходить за границы области просмотра. Поэтому выравнивание может привести к потере данных.
Чтобы предотвратить случайную потерю данных, вызванную выравниванием, теперь в CSS есть несколько новых ключевых слов, которые могут быть использованы совместно со свойствами выравнивания. Они определены в «Box Alignment» — спецификации, которая касается выравнивания во всех методах проектирования, включая Grid и Flexbox. В данный момент они поддерживаются только в Firefox. В нашем примере выше, если мы установим align-items: safe center, последний элемент будет выровнен по левому краю, а не центрирован. Это предотвратит потерю данных, вызванную центрированием элемента и поэтому вытолкнет его из-за границ области просмотра.
Если вам нужно выравнивание (даже если это приведет к переполнению), тогда вы можете указать unsafe center. В этом случае вы запросили, чтобы браузер выполнил выбранное вами выравнивание, независимо от того, что произойдет с содержимым. Если у вас Firefox, тогда вы можете видеть два примера: первый — с безопасным выравниванием, а второй — с небезопасным.
В докладе, на основании которого я писала эту статью, я описывала вёрстку как постоянную борьбу с переполнением. Одна из истин проектирования для веба заключается в том, что очень трудно узнать, насколько большим будет элемент, который содержит текст. Тем не менее, как я показала выше, у нас еще никогда не было столько способов управлять переполнением или возможностью переполнения. Это значит, что наша вёрстка может быть намного более устойчивой и мы можем создавать шаблоны, которые будут работать с различным объемом контента. Это может показаться лишь небольшими изменениями, но я думаю, что возможности, которые они открывают для нас, огромны.