Почему css grid выходит за границы родительского элемента
У меня иногда бывает третья причина использовать CSS Grid: предотвратить сдвиги в верстке. Я пытался придумать для этого приема прикольное сокращение, но у меня получилось лишь АСПНГ: «АнтиСдвиговый Прием с Наложением в Гридах». Вряд ли у меня получится похвастаться мастерством в «изобретении технических терминов» в резюме на LinkedIn, так что жду ваших предложений получше.
Давайте я объясню прием на реальных примерах. В этой статье я покажу:
- Реальную проблему сдвигов в верстке, с которой я столкнулся в работе над одним компонентом.
- Ограничения решения с абсолютным позиционированием.
- Преимущества решения с гридом.
Погодите, о каких вообще сдвигах идет речь?
Сдвиг в верстке — то, что происходит, когда обновление на странице заставляет что-то существенно переместиться. Чаще всего сдвиги в верстке происходят во время загрузки страницы, пока контент отрисовывается постепенно. Например, когда в страницу вставляется картинка с неизвестной высотой, прямо перед абзацем, который вы читаете, текст куда-то убегает, и это порядком раздражает. Еще такое часто бывает, когда сторонние скрипты (рекламные или партнерские сервисы) добавляют на страницу новые неизвестные элементы.
В этой статье я сосредоточусь на сдвигах в верстке, происходящих при переключении состояния компонентов интерфейса. Сдвиги во время загрузки я затрагивать не буду.
Полезные ссылки
Про CSS и гриды:
-
на MDN на Can I use на YouTube-канале Джейсона Ленгсторфа на CSS-Tricks (а также большую статью про гриды на этом сайте и другие материалы по соотв. тегу — прим. перев.)
- Присмотритесь к Firefox и его великолепному инспектору CSS-гридов
Компонент круговой диаграммы и компонент кнопки — части библиотеки компонентов Clever Cloud. Код открыт на Гитхабе и документация (с наглядным предпросмотром) опубликована с помощью Storybook.
Для начала — немного контекста
Я работаю в Clever Cloud, это платформа автоматизации IT. Наши клиенты выкладывают свой код и мы делаем за них всё остальное: билдим, деплоим, хостим, масштабируем, поддерживаем, восстанавливаем и т.д. Когда им нужно настраивать свои приложения, базы данных и прочие сервисы, они используют наш веб-интерфейс: «консоль». Большую часть времени я провожу над этим проектом, и выглядит он примерно так:
Когда я работал над этим компонентом, я старался не усложнять. Я представил себе, что наши пользователи и так поймут, что диаграмма относится к текущему приложению. Чтобы не загромождать экран, я решил убрать подробности типа точного количества запросов в подсказки, доступные с помощью мышки или касания. Но, визуально «очистив» диаграмму, я столкнулся с проблемой. Как объяснить следующие нюансы?
- Диаграмма показывает только данные за последние 24 часа.
- Каждый пункт в легенде можно кликнуть и показать/скрыть разные категории кодов статуса. Спасибо, Chart.js!
Доступного пространства слишком мало, чтобы добавить подробный заголовок вверху или внизу диаграммы. Так что, чтобы помочь пользователям узнать это, я добавил кнопку дополнительной информации (ℹ️) в правый верхний угол. При клике по этой кнопке диаграмма прячется, и вместо нее показывается краткий текст. Выглядит это примерно так:
По клику на кнопку «Закрыть» прячется этот краткий текст и диаграмма показывается снова. Реализовать поведение такого переключателя не так уж трудно. Возьмем упрощенную версию шаблона:
Решение с абсолютным позиционированием
До появления CSS Grid я бы решил эту проблему с помощью CSS-свойства position.
Первым делом я использовал бы visibility: hidden вместо display: none для скрытия «неактивной» панели:
Для такого HTML решение в CSS будет выглядеть примерно так:
Больше нет никаких сдвигов при переключении состояний, но остались ограничения:
Во-вторых, мне пришлось положиться на то, что размер компонента будет зависеть только от .info . В ситуации посложнее панелей может быть больше, чем две, и не всегда можно определить, какая из них должна управлять размером всего компонента.
Теперь посмотрим, как гриды справятся с этим лучше.
Элемент выезжает за пределы родительского блока
Выезжает div за пределы родительского
Выезжает див (см изображение) Если есть какие ещё какие предложения по улучшению рад буду получить.
Вывод картинки за пределы родительского блока
Здравствуйте! Нужно вывести изображение за пределы некоторой области, как на прикрепленном.
Смещение элемента за пределы родительского блока
Помогите плз. Нужно сделать такое как на картинке, т.е. поднять нижний блок к меньшему блоку, но.
Cмещение дочернего блока за пределы родительского при наличии overflow
Вобщем вот вся проблема: мне нужно скрыть все элементы, выходящие за рамки по Y, но при этом нужно.
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Div выходит за пределы родительского блока при масштабировании (+скрин)
Есть внешний div (outer-outer), первый внутренний (outer), второй внутренний (inner) и внутри него.
Может ли дочерний элемент выходить за пределы родительского?
я всегда думал что дочерний элемент не может выходить за пределы родительского но походу это не.
Текст выезжает за пределы блока div при разных разрешениях
текст задан в px, блок div статичный и тоже в px. сайт где можно посмотреть код ipodushki./ru .
При hover блок выезжает над бордером родительского элемента
Приветствую, подскажите плиз, как избавиться от следующего косяка. На главной блок "Услуги" -.
№1: Элементы с overflow-x поломают грид
Для нашего магазина использовался паттерн подменю, которое могло бы прокручиваться с помощью overflow-x , чтобы показать больше вариантов оплаты. Даже с примененным overflow-x грид-элемент растягивался до scrollWidth подменю. Оказывается, любой элемент с overflow-x , будь то блок <code> или адаптивная таблица, поломали бы грид. Вот наглядный пример.
Обычно с решением проблемы горизонтального переполнения справляется overflow-x: auto . Но не в этот раз. Ещё идея — обернуть элемент, попробовав всякие трюки с overflow: hidden , чтобы заставить раскладку подчиняться. Тоже нет.
Дело в том, что по умолчанию у грид-элементов стоит min-width: auto и их размер автоматически устанавливается по контенту в них. Оно устанавливает их min-width по ширине переполняющего блока. Поэтому для исправления глубоко вложенного переполняющего дочернего элемента вы, вопреки интуиции, не обращаете внимания на родительский элемент, а идете вверх по DOM-дереву до самого грид-элемента и обнуляете ему min-width .
Благодаря этому размеры грид-элемента с переполнением контента установятся правильно. Но не всегда.
Проблемы сдвига в верстке
В этом подходе есть большая проблема, в нем случаются сдвиги в верстке.
При работе над такими компонентами я стараюсь делать так, как считаю правильным: не задавать компоненту фиксированной высоты, чтобы он мог подстраиваться под свой контент. В данной ситуации это еще важнее, потому что я не могу знать заранее, сколько места понадобится для краткого текста (без скроллинга). Требуемый минимум высоты зависит от:
- Неизвестной ширины компонента, зависящей от контекста, в котором он используется
- Длины краткого текста, которая зависит от языка (английский либо французский)
В итоге, когда компонент содержит диаграмму, он оказывается чуть меньше по высоте, чем когда содержит краткий текст.
С французским текстом проблема еще острее, потому что он чуть длинее:
В зависимости от ситуации, это вроде бы безобидное изменение высоты может сильно повлиять на всю верстку и на положение скроллинга. Такие мелочи могут довести пользователей до бешенства:
- В лучшем случае другие части верстки слегка сместятся.
- В худшем случае кнопка под курсором мышки сдвинется и под ним окажется что-то другое (привет, кнопка поиска в Твиттере).
Видео внизу показывает, что происходит при переключении между состояниями.
Извините, ваш браузер не показывает видео прямо на странице.
Можете посмотреть на первый сдвиг верстки, когда я перехожу с «диаграммы» на «информацию». Соседняя гистограмма сдвигается вниз и карта увеличивается.
Теперь смотрите, что происходит, если я прокручу страницу вниз и вернусь к состоянию «диаграмма». Следите за курсором мышки. Я навел его на кнопку и больше не двигаю, но простой клик вызывает цепную реакцию:
- Высота компонента уменьшается до размера диаграммы.
- Высота всей страницы уменьшается.
- Вся страница чуть-чуть проскролливается вверх.
- Курсор мышки оказывается уже не над кнопкой, а над текстом.
Как нам теперь этот сдвиг предотвратить?
Блок за пределами родительского
Не могу понять причину того что блок вылазиет за приделы блока растягивая страницу, пытался у родителя сделать position absolute, а у дочернего элемента relative, не вышло. Дело было в хедере поэтому плюнул, вставил overflow hidden, вроде проблема решилась, но дальше при использовании @madia для разрешения планшета получается что остальные блоки тоже растягивают родительский блок, образуется пустое белое пространсво справа, в чем мб проблема? Стиль в коде потому что планируется использовать в e-mail рассылке (p.s верстаю уже 2ой раз, видимо ошибка в логике или пробелы в знаниях).
Добавлено через 9 минутВ @media div.main_content еще стоит margin-right : 0;
Выровнять фон по центру зв пределами родительского блока CSS
День добрый. Помогите решить проблемку. Уже который час бьюсь, ничего не получается. Есть.
Разместить блок за пределами родителя
Всем привет. Возможно ли разместить блок за пределами его родителя так, чтобы его было видно? При.
Блок на угол родительского блока
Как поставить div на угол родительского div в данном случае? <div <div.
Решение на гридах
CSS Grid уже поддерживается во всех «вечнозеленых» браузерах (т.е. автоматически обновляемых — прим. перев.). А значит, можно рассчитывать на возможность помещать несколько элементов в одну грид-область и накладывать их друг на друга.
Что вы имеете в виду под грид-областью?
Если вы не очень знакомы с CSS Grid, то, прежде чем читать статью дальше, я бы посоветовал:
Теперь, когда вы лучше знакомы с CSS-гридами, можно поговорить о теперь уже знаменитом «АнтиСдвиговом Приеме с Наложением в Гридах» (уж простите). Возьмем наш изначальный простой шаблон:
то наш компонент будет выглядеть вот так:
Благодаря чудесному инспектору CSS-гридов из отладчиика Firefox у нас есть подписи для рядов и колонок. Мы видим, что:
Это потому, что поведение по умолчанию — простая одноколоночная сетка: дочерние элементы размещаются по порядку. С помощью grid-column и grid-row можно заставить элементы разместиться в определенной области грида.
Например, если мы вот так разместим наши два элемента в одной и той же области:
то результат будет выглядеть так:
Если вас что-то смущает, не забывайте, что нужная панель будет скрыта с помощью visibility: hidden .
Извините, ваш браузер не показывает видео прямо на странице.
Больше никаких сдвигов!
В сравнении с решением на абсолютном позиционировании, мы улучшили ситуацию:
- Не нужна добавочная обертка .wrapper
- Будет прекрасно работать и более чем с двумя панелями
- Незачем гадать, какая панель будет управлять размером всего компонента
А теперь, бонусом, позвольте показать вам еще один реальный пример, где я использовал этот прием.
Что может поломать макет на гридах (CSS Grid Layout)
Как фронтенд-разработчика, меня ничто так не раздражает, как неожиданное появление горизонтального скроллбара на сайте. Однако, выстраивая раскладку страницы заказа с помощью CSS-гридов, я на удивление обнаружил что-то мистическое, что поломало мой контейнер. Я полагал, что с размерами у гридов всё решается автоматически.
В итоге я нашёл два способа поломать CSS-гриды. Как это бывает, я умудрился в одной раскладке сделать и то, и другое.
Можно ли назвать это багами гридов? Не совсем.
Такое поведение, как указал некто на StackOverflow, соответствует спецификации. Гриды перенимают поведение флексбоксов относительно min-width: auto , а у замещаемых элементов их min-width зависит от внутренних размеров. Так что само по себе это не баг.
Тем не менее, почти для каждой из моих раскладок мне приходилось применять вспомогательный класс к капризным грид-элементам. Чтобы у него было запоминающееся фирменное название, я назвал его «Fit Grid» (по-русски можно передать как «Влит-в-грид» — прим. перев.).
Гриды для тяжелых раскладок не должны задумываться, что в них за контент, и должны выдерживать самые разные сценарии. Было бы неплохо внедрить это в каждый проект, чтобы сделать грид-элементы максимально устойчивыми. Пусть это и не баг, но я отношу это к территории «Clearfix 2.0».
Как по мне, так замещаемые элементы всегда должны подчиняться и вмещаться в грид-полосы. Я был бы рад, если бы браузеры сошлись на этом. Единственный вопрос, который крутится в моей голове, это должны ли контролы формы, такие как прогрессбар, ползунок и числовые занимать всю грид-полосу. Решение — input , select < width: 100% >, но нутром чую, что не все этого захотят.
Спасибо Грегу Уитворту из Microsoft Edge за помощь в отладке и лучшем понимании замещаемых элементов.
№2: Контролы формы поломают грид
В нашей раскладке тоже использовался грид для размещения полей формы бок о бок. Я создал тестовый пример на CodePen с различными типами полей, чтобы изолировать эту проблему. При уменьшении окна браузера до момента появления горизонтального скролла (
380px) можно видеть, как поля выходят за границы грид-полосы.
В итоге, чтобы пофиксить подобные поля, придётся применить max-width: 100% , и хотя это в основном исправляет такое поведение в Chrome и Safari, некоторые элементы в этих браузерах и все подобные элементы в Firefox и Edge по-прежнему вываливаются за грид-полосу.
Потому что элементы <input> и им подобные ( <img> , <progress> , <select> , <video> ) обладают потенциальной способностью быть чем-то, называемым «Замещаемыми элементами»
Что ещё, чёрт возьми, за «Замещаемые элементы»?
Согласно MDN, замещаемый элемент — элемент, представление которого выходит за рамки CSS. Это ситуация, когда браузер получает разметку и внедряет элемент с чем-то вроде Shadow DOM. <video> — подходящий пример, но большинство контролов формы также попадают под это описание.
Замещаемые элементы существуют на какой-то спецификационной ничейной территории. Правила их оформления и отображения четко не определены, только лишь то, что у них «часто есть внутренние размеры». Поэтому каждый браузер по своему трактует внешний вид по умолчанию определённых элементов и использование замещаемых элементов в целом. На скриншоте ниже видно, как в зависимости от браузера выглядят замещаемые элементы и их размеры.
В нашей ситуации у некоторых элементов input есть фантомные «внутренние размеры», применяемые браузером. Они не отображаются в качестве браузерного стиля, ни во вкладке «Стили», ни в «Вычисленные стили», но их min-width около
180px для стандартного <input type="text"> .
Чтобы кроссбраузерно пофиксить «вываливание» элементов за границы грид-полосы, придётся переопределить этот внутренний размер замещаемых элементов.
Здесь есть побочный эффект, когда прогрессбар, и поля range и number теперь всегда занимают 100% грид-полосы. Это можно переопределить и настроить.
Предотвращение горизонтальных сдвигов
В предыдущем примере мы разбирались с высотой компонента, но этот прием можно использовать и для ширины. Если еще раз взглянуть на консоль Clever Cloud в целом, то в правом верхнем углу вы заметите несколько кнопок для управления состоянием приложения.
У кнопки «Stop app» («Остановить приложение») горизонтальные внутренние отступы больше, чем у остальных. Это потому, что при клике на эту самую кнопку текст на 3 секунды меняется на «Click to cancel» («Нажмите для отмены»), на случай, если вы запаниковали передумали.
Если бы не прием с гридом, изменение ширины при смене текста кнопки со «Stop app» на «Click to cancel» сдвинуло бы все остальные кнопки вот так:
На узких экранах перенос кнопок на новую строку мог бы вызвать еще больший сдвиг вёрстки, типа такого:
Извините, ваш браузер не показывает видео прямо на странице.
Благодаря «АнтиСдвиговому Приёму с Наложением в Гриде» (пожалуйста, пришлите свои идеи для названия, я уже не могу) не нужно гадать, в каком состоянии кнопка больше. Какова ни была бы длина у нормального текста и текста для отмены, кнопка всегда будет достаточного размера.
Извините, ваш браузер не показывает видео прямо на странице.
Больше никаких сдвигов!
Надеюсь, что эта статья помогла вам обратить внимание на сдвиги в вёрстке как потенциальную проблему, которую надо решать. Также надеюсь, что этот приём будет полезен и в ваших проектах.
Читайте также: