Альтернативный способ скрыть углы вложенных элементов с помощью «переполнение: скрыто»?

#html #css

#HTML #CSS

Вопрос:

Когда я устанавливаю overflow: hidden элемент контейнера в примере, углы исчезают, но гибкие элементы теряют высоту и уменьшаются, если вертикального пространства недостаточно.
Есть ли альтернативный способ скрыть углы или дополнительная настройка, чтобы элементы сохраняли свою высоту?

Отредактируйте еще несколько объяснений того, чего я пытаюсь достичь. Моя «установка»:

  1. навигационный элемент со 100% высотой окна и 40% «отзывчивой шириной»
  2. элемент контейнера внутри nav с радиусом границы
  3. 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 что это не решит эту проблему, я не думаю, что вам нужно будет установить a border-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 для сценария с различной шириной элементов, если вам интересно