CSS-сетка/гибкая сетка сжимается в зависимости от содержимого, но растет равномерно

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

Все, что я хочу, это:

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

Я мог бы сделать это, используя сетку или гибкость. К сожалению, я не могу добиться ожидаемого поведения, поскольку они либо растут в зависимости от своего содержимого (а не в зависимости от среднего размера), либо уменьшаются в зависимости от своего среднего размера, а не в зависимости от своего содержимого. Я включил фрагмент с двумя примерами реализации.

body {
  margin: 0;
  font-family: Verdana;
}

.small {
  width: 400px;
}

.medium {
  width: 800px;
}

.large {
  width: 1200px;
}

.container-flex {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  border: 1px solid black;
}

.item-flex {
  display: flex;
  flex-direction: column;
  flex-basis: auto;
  flex-shrink: 1;
  flex-grow: 1;
  overflow: hidden;
  padding: 20px;
  background-color: green;
  border: 1px solid red;
  min-width: 0;
}

.title {
  background-color: white;
  flex-grow:0;
  text-align: center;
  vertical-align: middle;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  min-width: 0;
}

.container-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 1fr);
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
  border: 1px solid black;
}

.item-grid {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 20px;
  background-color: green;
  border: 1px solid red;
  min-width: 0;
}
<div class = "small">
<h2>Small</h2>
<h4>Flex</h4>
<div class = "container-flex">
<div class = "item-flex">
<div class = "title">Title</div>
</div>
<div class = "item-flex">
<div class = "title">Long Title</div>
</div>
<div class = "item-flex">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-flex">
<div class = "title">Title</div>
</div>
</div>
<h4>Grid</h4>
<div class = "container-grid">
<div class = "item-grid">
<div class = "title">Title</div>
</div>
<div class = "item-grid">
<div class = "title">Long Title</div>
</div>
<div class = "item-grid">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-grid">
<div class = "title">Title</div>
</div>
</div>
</div>
<div class = "medium">
<h2>Medium</h2>
<h4>Flex</h4>
<div class = "container-flex">
<div class = "item-flex">
<div class = "title">Title</div>
</div>
<div class = "item-flex">
<div class = "title">Long Title</div>
</div>
<div class = "item-flex">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-flex">
<div class = "title">Title</div>
</div>
</div>
<h4>Grid</h4>
<div class = "container-grid">
<div class = "item-grid">
<div class = "title">Title</div>
</div>
<div class = "item-grid">
<div class = "title">Long Title</div>
</div>
<div class = "item-grid">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-grid">
<div class = "title">Title</div>
</div>
</div>
</div>
<div class = "large">
<h2>Large</h2>
<h4>Flex</h4>
<div class = "container-flex">
<div class = "item-flex">
<div class = "title">Title</div>
</div>
<div class = "item-flex">
<div class = "title">Long Title</div>
</div>
<div class = "item-flex">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-flex">
<div class = "title">Title</div>
</div>
</div>
<h4>Grid</h4>
<div class = "container-grid">
<div class = "item-grid">
<div class = "title">Title</div>
</div>
<div class = "item-grid">
<div class = "title">Long Title</div>
</div>
<div class = "item-grid">
<div class = "title">Even longer Title</div>
</div>
<div class = "item-grid">
<div class = "title">Title</div>
</div>
</div>
</div>

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

Первые два пункта вы можете достичь с помощью grid-template-columns:repeat(4, minmax(min-content, 1fr));, но я не могу (пока!) разобраться с последним пунктом.

Adam 03.07.2024 14:25

@ Адам, Адам, я пытался, но все, что он делает, это переполняет своего родителя. И в моей реальной реализации это не имеет никакого эффекта. Мне также нужно придерживаться auto-fill, так как количество предметов может варьироваться.

Tim Nikischin 03.07.2024 15:13

@ Адам, я продолжил расследование, и это действительно имеет значение. Хотя для меня было бы лучше использовать grid-auto-columns: minmax(min-content, 1fr); (и удалить grid-template-columns) вместо того, чтобы придерживаться поведения, подобного автозаполнению.

Tim Nikischin 03.07.2024 15:36
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
1
3
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

с 3 различными вариантами поведения контейнера вам необходимо изменить характеристики карт.

«карточкам с небольшим контейнером» нужен max-width с overflow: hidden и text-overflow: ellipsis.

«Картам среднего контейнера» требуется min-width, а по умолчанию flex-shrink отключено.

«Картам больших контейнеров» необходимо предварительно задать ширину, чтобы все они имели одинаковую ширину:

.container {
  display: flex;
  width: 100%;
}

.container>* {
  box-shadow: inset 0 0 0 0.5em rgba(0, 200, 0, 0.6);
  border: 1px dashed red;
  padding: 0.5em;
  text-align: center;
  white-space: nowrap;
}

@media only screen 
  and (min-width: 320px) 
  and (max-width: 524px) {
    .container > * {
      max-width: 5em;
      overflow: hidden;
      text-overflow: ellipsis;
    }
}

@media only screen 
  and (min-width: 525px) 
  and (max-width: 719px) {
    .container > * {
      min-width: 3em;
      flex-shrink: 0;
    }
}

@media only screen
  and (min-width: 720px) {
    .container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    }
}
<div class = "container">
  <div>Title</div>
  <div>Long Title</div>
  <div>Even longer Title</div>
  <div>Title</div>
</div>

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

Извините, если я не совсем ясно выразился в своем вопросе, но я прошу гибкого решения, а не фиксированного размера. Также мои предметы могут иметь другое количество или содержание.

Tim Nikischin 03.07.2024 15:04

для отзывчивости вам просто нужно поместить код в медиа-запросы вместо разных классов

tacoshy 03.07.2024 15:10

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

Tim Nikischin 03.07.2024 15:15

это решение для отзывчивости, а не для второй задачи. чего вы не можете сделать без JavaScript. вы можете использовать flex-grow: 1, который равномерно распределит оставшееся пространство, но не будет одинакового размера всех элементов. возможно, есть решение JS, которое мне нужно проверить

tacoshy 03.07.2024 15:17

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

Tim Nikischin 03.07.2024 15:23
Ответ принят как подходящий

Я решил это в Codepen, вот ссылка на Codepen

Вот HTML

<div class = "navbar">
  <a href = "" class = "navbarLink">
    <div class = "text">
      Title
    </div>
  </a>
  <a href = "" class = "navbarLink">
    <div class = "text">
      Long Title
    </div>
  </a>
  <a href = "" class = "navbarLink">
    <div class = "text">
      Even longer Title
    </div>
  </a>
  <a href = "" class = "navbarLink">
    <div class = "text">
      Title
    </div>
  </a>
</div>

CSS

body {
  margin: 0;
}

.navbar {
  display: grid;
  grid-template-columns: auto auto auto auto;
  
  padding 10px
}

.navbar > a {
  text-align: center;
  color: black;
  text-decoration: none;
  
  padding: 10px;
  border: 5px solid green;

  font-size: 30px;
}

.navbar > a > .text {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 1; /*Number of lines before an ellipsis... pops up */
  -webkit-box-orient: vertical;
}


Делает работу. Большой! Достойная работа сделана! Вместо grid-template-columns: auto auto auto auto; вы можете просто использовать grid-auto-flow: column;, чтобы сделать слово более общим.

Tim Nikischin 05.07.2024 10:34

@TimNikischin Честно говоря, я никогда раньше не видел grid-auto-flow, но спасибо, что сообщили мне, большое спасибо

Martin Arreola 05.07.2024 18:00

Другие вопросы по теме