#html #css
#HTML #CSS
Вопрос:
Когда я устанавливаю overflow: hidden
элемент контейнера в примере, углы исчезают, но гибкие элементы теряют высоту и уменьшаются, если вертикального пространства недостаточно.
Есть ли альтернативный способ скрыть углы или дополнительная настройка, чтобы элементы сохраняли свою высоту?
Отредактируйте еще несколько объяснений того, чего я пытаюсь достичь. Моя «установка»:
- навигационный элемент со 100% высотой окна и 40% «отзывчивой шириной»
- элемент контейнера внутри nav с радиусом границы
- flex-элементы внутри контейнера с
flex-wrap: wrap
фоном и фоном
Моя цель:
- Чтобы удалить фон гибких элементов, который в настоящее время виден в углах за пределами радиуса границы контейнеров.
Есть ли способ добиться этого только с помощью CSS?
Решения, о которых я думал / пробовал:
- предоставление контейнера
overflow:hidden
скрывает угол гибких элементов, но они сжимаются, если вертикального пространства недостаточно - настройка только
overflow-x: hidden
кажется установленнойoverflow-y: auto
, и появляется вертикальная полоса прокрутки, которой не должно быть - установка радиуса границы для гибких элементов в «угловых положениях» не является опцией, так как позиции различаются в зависимости от ширины контейнера и
flex-wrap
- удаление параметра
height
илиmin-height
навигации решает проблему потери высоты элементов. Но тогда в навигации больше нет полосы прокрутки, и содержимое в нижней части навигации покидает экран, если на нем недостаточно места
Вот как должен выглядеть результат
html, body { position: relative; width: 100%; height: 100%; margin: 0; padding: 0; } nav { box-sizing: border-box; border: 1px solid black; height: 100%; width: 40%; display: flex; flex-direction: column; overflow: scroll; } #spacer { min-height: 400px; border: 2px solid darkmagenta; } #container { display: flex; flex-wrap: wrap; border: 3px solid teal; border-radius: 20px; /* overflow: hidden; */ } .flex-item { text-align: center; flex-grow: 1; padding: 40px 20px; border: 2px solid orange; background: darkorange; }
lt;navgt; lt;div id="spacer"gt;lt;/divgt; lt;div id="container"gt; lt;div class="flex-item"gt;Alllt;/divgt; lt;div class="flex-item"gt;Adjectivelt;/divgt; lt;div class="flex-item"gt;Adverblt;/divgt; lt;div class="flex-item"gt;Conjunctionlt;/divgt; lt;div class="flex-item"gt;Nounlt;/divgt; lt;div class="flex-item"gt;Numberlt;/divgt; lt;div class="flex-item"gt;Prepositionlt;/divgt; lt;div class="flex-item"gt;Pronounlt;/divgt; lt;div class="flex-item"gt;Verblt;/divgt; lt;/divgt; lt;/navgt;
This is a javascript version which would achieve what I’m looking for, but I still hope there’s something I’m missing to do this with CSS only?
document.body.onresize = setBorderRadius; function setBorderRadius() { let r = "var(--border-radius)" let flexItems = [...document.getElementsByClassName("flex-item")]; flexItems.forEach(item =gt; item.style.borderRadius = "0") let topTmp = 0 const sortedByRows = flexItems.reduce((acc, item) =gt; { let top = item.getBoundingClientRect().top if (top gt; topTmp) acc.push([item]) else acc[acc.length - 1].push(item) topTmp = top return acc }, []) let firstRow = sortedByRows[0] let upperLeft = firstRow[0] let upperRight = firstRow[firstRow.length-1] let lastRow = sortedByRows[sortedByRows.length-1] let lowerLeft = lastRow[0] let lowerRight = lastRow[lastRow.length-1] upperLeft.style.borderTopLeftRadius = r upperRight.style.borderTopRightRadius = r lowerLeft.style.borderBottomLeftRadius = r lowerRight.style.borderBottomRightRadius = r } setBorderRadius();
html, body { position: relative; width: 100%; height: 100%; margin: 0; padding: 0; } nav { --border-radius: 15px; box-sizing: border-box; border: 1px solid black; height: 100%; width: 80%; display: flex; flex-direction: column; overflow: scroll; } #spacer { min-height: 400px; border: 2px solid darkmagenta; } #container { display: flex; flex-wrap: wrap; } .flex-item { flex-grow: 1; padding: 40px 20px; border: 2px solid orange; background: darkorange; }
lt;navgt; lt;div id="spacer"gt;lt;/divgt; lt;div id="container"gt; lt;div class="flex-item"gt;Alllt;/divgt; lt;div class="flex-item"gt;Adjectivelt;/divgt; lt;div class="flex-item"gt;Adverblt;/divgt; lt;div class="flex-item"gt;Conjunctionlt;/divgt; lt;div class="flex-item"gt;Nounlt;/divgt; lt;div class="flex-item"gt;Numberlt;/divgt; lt;div class="flex-item"gt;Prepositionlt;/divgt; lt;div class="flex-item"gt;Pronounlt;/divgt; lt;div class="flex-item"gt;Verblt;/divgt; lt;/divgt; lt;/navgt;
Комментарии:
1. Что вы здесь подразумеваете под «углами»? Вы имеете в виду, что ваша проблема заключается в том, что оранжевые блоки гибких элементов имеют квадратные углы, в то время как контейнер имеет закругленные углы? Потому
overflow
что это не решит эту проблему, я не думаю, что вам нужно будет установить aborder-radius
на гибкие элементы. Кроме того, гибкие элементы могут уменьшаться, поскольку они наследуютсяoverflow: hidden
от родительского контейнера. Но главное: что именно вы пытаетесь сделать?2. @JohnP Я добавил еще несколько пояснений к своему вопросу
Ответ №1:
.flex-item:first-child { flex-grow: 1; padding: 40px 40px; border: 2px solid orange; background: darkorange; border-radius: 20px 0px 0px 20px; } .flex-item:last-child { flex-grow: 1; padding: 40px 40px; border: 2px solid orange; background: darkorange; border-radius: 0px 20px 20px 0px; }
используйте следующие параметры :первый ребенок :последний ребенок, чтобы сгибать элементы в радиусе границы контейнера
Комментарии:
1. это сработало бы, если бы это была всего одна строка элементов, но контейнер имеет
flex-wrap: wrap
, и положение элементов в углу варьируется в зависимости от ширины окна
Ответ №2:
переполнение-x: скрыто, тогда оно будет работать, но со прокруткой.
Комментарии:
1. Спасибо, к сожалению, версия с прокруткой не подходит
Ответ №3:
Если вы удалите height: 100%
из main
ИЛИ измените его на min-height: 100%
, то overflow: hidden
#container
он будет работать.
Комментарии:
1. Удаление
height
или настройкиmin-height
main/nav решает проблему потери высоты элементов. Но тогда в навигации больше нет полосы прокрутки, и содержимое в нижней части навигации покидает экран, если на нем недостаточно места
Ответ №4:
Если есть способ сделать это в CSS3, я недостаточно умен, чтобы придумать его. Проблема в том, как вы сказали, что overflow: hidden
это нарушает то, как он должен себя вести, и border-radius
на первом и последнем элементах .flex-item
не будет работать с каждым размером окна.
Проблема с этим border-radius
подходом заключается в том, что при изменении размера окна вы не знаете, какие .flex-item
элементы нужны border-radius
. Какие из них должны быть, зависит от того, сколько там строк. Я не знаю никакого способа определить это в чистом CSS3, но в JavaScript это несложно. Используя JS, вы можете получить ширину #container
элемента и ширину .flex-item
элементов. С помощью этого вы можете определить количество .flex-item
элементов в строке ( #container
ширина / .flex-item
ширина) и количество строк (количество .flex-item
элементов / количество строк). Затем вы можете установить border-radius
на первом .flex-item
элементе, последнем в первой строке, первом в последней строке и последнем довольно легко.
Поскольку это сценарий, он будет запускаться только один раз, поэтому вам также необходимо выполнять описанное выше каждый раз при изменении размера окна. Поэтому мы поместим все вышесказанное в функцию и установим прослушиватель событий изменения размера в теле документа для этой функции. Поскольку это функция, нам придется вызывать ее при загрузке страницы, чтобы она устанавливала границы в первый раз.
Итак, вот все это в форме кода (HTML и CSS такие же, как у вас, только JS новый). Он не особенно хорошо просматривается в маленьком окне здесь, поэтому я бы рекомендовал вставить его в другое окно.
document.body.onresize = setBorderRadii; function setBorderRadii() { let r = "15"; let flex_items = document.getElementsByClassName("flex-item"); for (let i = 0; i lt; flex_items.length; i ) { flex_items[i].style.borderRadius = "0 0 0 0"; flex_items[i].innerHTML = "flex item"; } let items = flex_items.length; let containerWidth = document.getElementById("container").clientWidth; let flexWidth = flex_items[0].clientWidth; let rowSize = Math.floor(containerWidth / flexWidth); let rows = Math.ceil(items / rowSize); switch (rowSize) { case 1: flex_items[0].style.borderRadius = r "px " r "px 0 0"; flex_items[items - 1].style.borderRadius = "0 0 " r "px " r "px"; break; case items - 1: flex_items[0].style.borderRadius = r "px 0 0 0"; flex_items[6].style.borderRadius = "0 " r "px 0 0"; flex_items[items - 1].style.borderRadius = "0 0 " r "px " r "px"; break; case items: flex_items[0].style.borderRadius = r "px 0 0 " r "px"; flex_items[items - 1].style.borderRadius = "0 " r "px " r "px 0"; break; default: flex_items[0].style.borderRadius = r "px 0 0 0"; flex_items[rowSize - 1].style.borderRadius = "0 " r "px 0 0"; flex_items[rowSize * (rows - 1)].style.borderRadius = "0 0 0 " r "px"; flex_items[items - 1].style.borderRadius = "0 0 " r "px 0"; } } setBorderRadii();
html, body { position: relative; width: 100%; height: 100%; margin: 0; padding: 0; } nav { box-sizing: border-box; border: 1px solid black; height: 100%; width: 40%; display: flex; flex-direction: column; overflow: scroll; } #spacer { min-height: 400px; border: 2px solid darkmagenta; } #container { display: flex; flex-wrap: wrap; border: 3px solid teal; border-radius: 20px; } .flex-item { flex-grow: 1; padding: 40px 40px; border: 2px solid orange; background: darkorange; }
lt;navgt; lt;div id="spacer"gt;lt;/divgt; lt;div id="container"gt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;div class="flex-item"gt;flex itemlt;/divgt; lt;/divgt; lt;/navgt;
Это должно работать даже с разным количеством .flex-item
элементов, если их несколько.
r
Переменная там определяла border-radius
применяемые к .flex-item
элементам. Это меньше 20, чтобы убедиться, что между углом #container
элемента и углами элементов нет пробелов .flex-item
.
Если вы не знакомы с использованием JS в своих HTML-документах, вы используете lt;scriptgt;
тег. Вы можете вставить весь код между тегами следующим образом:
lt;scriptgt; /* code here */ lt;/scriptgt;
или используйте .js
файл со сценарием внутри и тегом сценария, подобным этому:
lt;script src=" {script file location} "gt;lt;/scriptgt;
Обязательно поместите элемент сценария после соответствующих HTML-элементов, иначе он не будет работать (если он находится перед ними, он попытается выполнить действие с элементами, которые еще не существуют, что приведет к ошибке).
Комментарии:
1. Спасибо за усилия по написанию версии javascript. Поскольку это уже было достаточно сложно, приведенный мной пример был фактически упрощен, и не все элементы будут иметь одинаковую ширину… Я добавил картинку к вопросу и все еще надеюсь на решение CSS. Если мне придется использовать js, я, вероятно, установлю радиус с
elem.style.borderTopLeftRadius
помощью,elem.style.borderBottomRightRadius
, … возможно, в конце будет не меньше кода (я думаю, что все значения придется сбросить в начале), но в целом это будет легче читать2. Ширина элемента используется только для определения того, сколько элементов будет в каждой строке перед последней, так как до этого они должны сохранять постоянную ширину. Он округляет первый элемент, последний, последний в первой строке и следующий за последним в предпоследней строке, который всегда является первым в последней строке, но вычисление позиции таким образом предотвращает ошибки из-за переменной ширины, которая связана с тем, что элементы в строке не являются постоянными до конца. По крайней мере, это работает с предоставленным вами кодом.
3. Мне жаль, что мой вопрос был недостаточно точным и вводил в заблуждение, я постараюсь избежать этого в будущем. Я добавил версию javascript для сценария с различной шириной элементов, если вам интересно