Удалить лишнее пространство справа после обертывания элементов с помощью flex-wrap, сохраняя при этом равные интервалы между элементами

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

Проблема в том, что когда они начинают оборачиваться, остается куча места, оставшегося от обёрнутого элемента.

Между всеми элементами должно быть 8 пикселей, включая тот, который не переносится. Как сделать так, чтобы не было пустого места?

Вот рабочий пример:

const App = () => {

  return (
    <div>
      <p>see the items below, regardless of how many I have, I need to hide whatever doesn't fit on the line screen.</p>
      <p>All items need to have 8px gap in between them, including the green one which does not wrap.</p>
      <h5>How can this be done?</h5>
      <div className = "container">
        <div className = "wrap-container">
          {Array.from({ length: 100 }).map((_, index) => <div className = "item" key = {index}>{index}</div>)}
        </div>
        <div className = "non-wrap-item"> I need to be 8px from the last visible item</div>
      </div>
    </div>
  )
}


ReactDOM.render(
    <App />,
    document.getElementById('app')
);
.container {
  display: flex;
}

.wrap-container {
  max-width: 500px;
  display: flex;
  flex-wrap: wrap;
  height: 80px;
  overflow: hidden;
  gap: 8px;
  
  border: 1px solid red;
  margin-right: 8;
}

.item {
  width: 80px;
  height: 80px;
  background-color: blue;
  color: white;
}

.non-wrap-item {
  width: 80px;
  height: 80px;
  background-color: green;
  color: white;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id = "app"></div>

Примечание. Я видел похожие вопросы, но ни один из них не касается того факта, что мне всегда нужен промежуток в 8 пикселей между элементами. С теми, с кем я сталкивался, я теряю этот контроль. Есть ли что-нибудь вокруг этого?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
0
226
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Использование grid вместо flexbox упростит задачу, например:

const App = () => {

  return (
    <div>
      <p>see the items below, regardless of how many I have, I need to hide whatever doesn't fit on the line screen.</p>
      <p>All items need to have 8px gap in between them, including the green one which does not wrap.</p>
      <h5>How can this be done?</h5>
      <div className = "container">
        <div className = "wrap-container">
          {Array.from({ length: 100 }).map((_, index) => <div className = "item" key = {index}>{index}</div>)}
        </div>
        <div className = "non-wrap-item"> I need to be 8px from the last visible item</div>
      </div>
    </div>
  )
}

ReactDOM.render(
    <App />,
    document.getElementById('app')
);
.container {
  display: grid;
  grid-template-columns:1fr 80px;
  gap: 8px;
  /* if you want some max-width, put it here instead*/
  max-width: 500px;
}

.wrap-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px,1fr));
  gap: 8px;
}

.item {
  height: 80px;
  background-color: blue;
  color: white;
}

.non-wrap-item {
  height: 80px;
  background-color: green;
  color: white;
  
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id = "app"></div>

Это ответ на первоначальный вопрос, поэтому я награжу вас наградой, так как вы были первым. Однако у меня есть дополнение: в моем реальном случае не все элементы имеют одинаковый размер, и я не обязательно знаю, какого размера они будут. Вы знаете, как это можно решить?

theJuls 20.03.2022 20:24

Спасибо @theJuls! Не тот же размер с точки зрения ширины, верно?

yousoumar 20.03.2022 20:32

Мой плохой, должен был указать. Да, это было бы для разной ширины.

theJuls 20.03.2022 22:07

const App = () => {

    return ( <
        div >
        <
        p > see the items below, regardless of how many I have, I need to hide whatever doesn 't fit on the line screen.</p> <
        p > All items need to have 8 px gap in between them, including the green one which does not wrap. < /p> <
        h5 > How can this be done ? < /h5> <
        div className = "container" >
        <
        div className = "wrap-container" > {
          Array.from({
            length: 100
          }).map((_, index) => < div className = "item"
            key = {
              index
            } > {
              index
            } < /div>)} <
            /div> <
            div className = "non-wrap-item" > I need to be 8 px from the last visible item < /div> <
            /div> <
            /div>
          )
        }


        ReactDOM.render( <
          App / > ,
          document.getElementById('app')
        );
.container {
  display: flex;
  gap: 8px;
}

.wrap-container {
  max-width: 500px;
  display: flex;
  flex-wrap: wrap;
  height: 80px;
  overflow: hidden;
  gap: 8px;
  border: 1px solid red;
  margin-right: 8;
}

.item {
  flex: 1 0 80px;
  height: 80px;
  background-color: blue;
  color: white;
}

.non-wrap-item {
  flex: 0 0 80px;
  height: 80px;
  background-color: green;
  color: white;
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id = "app"></div>

Боюсь, что ширина была в стилях элементов по какой-то причине :( Разрешить растягивание элементов не вариант.

theJuls 17.03.2022 23:36

О, так вы хотите, чтобы предмет, который не должен сворачиваться, двигался, чтобы заполнить пространство? Или расширить, чтобы заполнить пространство?

sol 18.03.2022 00:50

@theJuls ответ, который вы приняли, также растягивает элементы, поэтому вам нужно четко понимать значение растяжение. В качестве примечания: в другом ответе (мом) нет ни растяжения, ни сжатия, ширина сохраняется такой, как определено.

Temani Afif 20.03.2022 20:30

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

theJuls 20.03.2022 22:05

@theJuls нет, в моем ответе нет растяжения, ширина фиксирована. Я не говорю об ответе это. Мой ответ другой.

Temani Afif 20.03.2022 22:08

@TemaniAfif Я знаю, что вы имели в виду свой ответ выше. Я имею в виду, что и ваш, и другой работали почти одинаково в моем реальном приложении. Натяжения принятого за актуальное не заметил. Причина, по которой я выбрал именно его, а не ваш, сводилась к тому, что он оказался первым. А теперь я уже не уверен. Придется подумать.

theJuls 20.03.2022 23:18

@theJuls Меня не волнует, какой вы будете использовать или какой вы примете. Речь идет о точности ваших требований. Вы сказали здесь, что не хотите растягиваться, а позже приняли другой ответ с эффектом растяжения, который сбивает с толку.

Temani Afif 20.03.2022 23:27

@TemaniAfif понятно, но я ценю всю помощь и хочу вознаградить всех за это должным образом :) Я думаю, что проблема заключалась в том, что основное внимание было уделено моему реальному приложению, которое, конечно, не так просто, как этот пример. И я очень ценю, что это вынесено на обсуждение здесь.

theJuls 20.03.2022 23:29

Используйте сетку CSS, как показано ниже. Я удалил часть реакции, чтобы сделать демонстрацию простой, но я не трогал структуру HTML.

.container {
  display: grid;
  max-width: 600px; /* move the max-width here */
  grid-template-columns: repeat(auto-fit, 80px); /* 80px columns */
  column-gap: 8px; /* your gap here */
}

.wrap-container {
  display: grid;
  grid-column: 1/-2; /* take all the column minus the last one (the green will take the last one)*/
  grid-template-columns: inherit; /* inherit the same column configuration */
  column-gap: inherit; /* and same gap */
  grid-template-rows: 80px; /* one row equal to 80px */
  grid-auto-rows: 0; /* all the others row equal to 0 */
  overflow: hidden; 
  outline: 1px solid red;
}
/* no need to define width or height for items*/
.item {
  background-color: blue;
  color: white;
}

.non-wrap-item {
  background-color: green;
  color: white;
}
<div>
  <p>see the items below, regardless of how many I have, I need to hide whatever doesn't fit on the line screen.</p>
  <p>All items need to have 8px gap in between them, including the green one which does not wrap.</p>
  <h5>How can this be done?</h5>
  <div class = "container">
    <div class = "wrap-container">
      <div class = "item">1</div>
      <div class = "item">2</div>
      <div class = "item">3</div>
      <div class = "item">4</div>
      <div class = "item">5</div>
      <div class = "item">6</div>
      <div class = "item">7</div>
      <div class = "item">8</div>
      <div class = "item">9</div>
      <div class = "item">10</div>
      <div class = "item">11</div>
      <div class = "item">12</div>
      <div class = "item">13</div>
      <div class = "item">14</div>
    </div>
    <div class = "non-wrap-item"> I need to be 8px from the last visible item</div>
  </div>
</div>

Простым решением было бы просто оправдать содержимое: пространство-равномерно, а затем добавить отступ влево 8px для последнего элемента...

так что левая сторона в div и правая тоже. Чем вы могли бы просто равномерно распределить элементы в левом div, а затем все время оставить правый статическим.

Если мне нужно предоставить точный код, чтобы это работало, чтобы вы могли нажать ниндзя ctrlCctrlV, просто дайте мне знать: P

Почему ты освистываешь меня? Потому что я не дал точный код? XP

Ruben Verster 22.03.2022 14:26

Спасибо за вашу помощь, я не был тем, кто проголосовал против вас. Хотелось бы, чтобы люди не делали этого, в том, как вы ответили, нет ничего плохого :( Что касается самого вашего ответа, к сожалению, это не вариант, потому что мне очень конкретно сказали, что между всеми элементами должны быть промежутки в 8 пикселей, которые, к сожалению, потеряны в space-evenly.

theJuls 22.03.2022 19:50

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

Тем не менее, .container будет иметь два столбца: первый имеет минимальную ширину 80 пикселей и максимальную ширину 500 пикселей; второй имеет ширину 80px. Эта сетка имеет зазор в 8 пикселей между столбцами.

.wrap-container содержит неопределенное количество элементов с промежутком в 8 пикселей. Ширина каждого элемента начинается с 80 пикселей и может увеличиваться до оставшегося свободного места.

.container, .wrap-container {
  display: grid;
  gap: 8px;
}

.container {
  grid: auto / minmax(80px, 500px) 80px;
}

.wrap-container {
  grid: auto / repeat(auto-fit, minmax(80px, 1fr));
}

.item, .item-2 {
  height: 80px;
  color: white;
}

.item {
  background: blue;
}

.item-2 {
  background: green;
}

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