Flexbox space-between имеет дополнительный зазор в 1 пиксель в конце при использовании calc()

Я разрабатывал систему сетки с использованием flexbox justify-content: space-between; и заметил, что на экранах определенных размеров (примерно через каждый второй пиксель) в конце определенных столбцов появляется зазор в 1 пиксель.

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

Пример

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 550px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^ = "col"] {
  border: 2px solid red;
}

.col-12 {
  flex-basis: calc(100% - 4px);
}

.col-11 {
  flex-basis: calc(11/12*100% - (1.167 - 11/12)*24px);
}

.col-10 {
  flex-basis: calc(5/6*100% - (1.167 - 5/6)*24px);
}

.col-9 {
  flex-basis: calc(3/4*100% - (1.167 - 3/4)*24px);
}

.col-8 {
  flex-basis: calc(2/3*100% - (1.167 - 2/3)*24px);
}

.col-7 {
  flex-basis: calc(7/12*100% - (1.167 - 7/12)*24px);
}

.col-6 {
  flex-basis: calc(1/2*100% - (1.167 - 1/2)*24px);
}

.col-5 {
  flex-basis: calc(5/12*100% - (1.167 - 5/12)*24px);
}

.col-4 {
  flex-basis: calc(1/3*100% - (1.167 - 1/3)*24px);
}

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*24px);
}

.col-2 {
  flex-basis: calc(1/6*100% - (1.167 - 1/6)*24px);
}

.col-1 {
  flex-basis: calc(1/12*100% - (1.167 - 1/12)*24px);
}
<div class = "row">
  <div class = "col-12">col-12</div>
  <div class = "col-6">col-6</div>
  <div class = "col-6">col-6</div>
  <div class = "col-4">col-4</div>
  <div class = "col-4">col-4</div>
  <div class = "col-4">col-4</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-6">col-6</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-4">col-4</div>
  <div class = "col-8">col-8</div>
  <div class = "col-7">col-7</div>
  <div class = "col-5">col-5</div>
  <div class = "col-6">col-6</div>
  <div class = "col-4">col-4</div>
  <div class = "col-2">col-2</div>
</div>

Вот рабочий Fiddle, чтобы вам было легче изменить его размер.

JSFiddle

*Примечание: Я знаю, что делаю какие-то сумасшедшие вещи с calc(), но даже если вы просто вычитаете 5px вместо (1.167 - 1/12)*24px), проблема все еще существует.

Это ошибка флексбокса?

Что мне нужно сделать, чтобы убрать пробел в конце этих столбцов?

Вероятно, субпиксельное округление.

Paulie_D 19.06.2019 16:58

Честно говоря, я думаю, вам лучше использовать CSS-Grid.

Paulie_D 19.06.2019 17:00

Это лучший вариант @Paulie_D, но мне нужно поддерживать определенные браузеры, которые не поддерживаются css-grid.

Hunter Turner 19.06.2019 17:03

Не существует точного способа избежать округления субпикселей с помощью CSS. Либо сделайте их шириной 1 пиксель, чтобы соответствовать родителю, и используйте overflow: hidden, либо используйте скрипт, чтобы вы могли самостоятельно выполнить математику и убедиться, что округление соответствует вашим потребностям.

Asons 19.06.2019 18:20
Приемы 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 сценарий полностью изменился.
10
4
1 513
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

ваша проблема связана с col-3 и col-6

до:

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*24px);
}

после:

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*25px);
}

попытайся:

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 700px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^ = "col"] {
  border: 2px solid red;
}

.col-12 {
  flex-basis: calc(100% - 4px);
}

.col-11 {
  flex-basis: calc(11/12*100% - (1.167 - 11/12)*24px);
}

.col-10 {
  flex-basis: calc(5/6*100% - (1.167 - 5/6)*24px);
}

.col-9 {
  flex-basis: calc(3/4*100% - (1.167 - 3/4)*24px);
}

.col-8 {
  flex-basis: calc(2/3*100% - (1.167 - 2/3)*24px);
}

.col-7 {
  flex-basis: calc(7/12*100% - (1.167 - 7/12)*24px);
}

.col-6 {
  flex-basis: calc(1/2*100% - (1.167 - 1/2)*25px);
}

.col-5 {
  flex-basis: calc(5/12*100% - (1.167 - 5/12)*24px);
}

.col-4 {
  flex-basis: calc(1/3*100% - (1.167 - 1/3)*24px);
}

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*25px);
}

.col-2 {
  flex-basis: calc(1/6*100% - (1.167 - 1/6)*24px);
}

.col-1 {
  flex-basis: calc(1/12*100% - (1.167 - 1/12)*24px);
}

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

Temani Afif 08.07.2019 14:13

.col-3 и .col-6

Hossein Shourabi 08.07.2019 18:30

не использует border: 2px solid red; использование границы цвета фона добавляет 2 пикселя

Dean Van Greunen 09.07.2019 20:32
Ответ принят как подходящий

Эта проблема

Я немного поиграл с этой проблемой, прежде чем пришел к решению. Шаги следующие:

Сначала я преобразовал все, чтобы использовать стандартный формат

calc(a/12 * 100% - (7/6 - a/12) * 24px) где a = "col number"

Затем я начал экспериментировать с числом, чтобы увидеть фактический результат без единиц измерения (конечно).

  • 1: -17,6666...
  • 2: -7,3333...
  • 3: 3
  • 4: 13.3333...
  • 5: 23,6666...
  • 6: 34
  • 7: 44.3333...
  • 8: 54,6666...
  • 9: 65
  • 10: 75.3333...
  • 11: 85,6666...
  • 12: 96

Из этого мы можем видеть три вещи

  • Любое число, которое делится на 3, является целым числом.
  • Следующее число заканчивается повторением x.3333...
  • Второе число заканчивается на x.6666...

Примечание: 1 и 2 являются особыми случаями и меняются местами, потому что их выход на самом деле отрицательный. Мы можем предположить, что их числа были бы положительными в реальном мире и соответствовали бы другим.

После этого определить фактическую проблему в уравнении было легко: a/12 * 100%

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

Исправление

Мы хотели бы, чтобы эти ошибки округления не каскадировались, поэтому у нас есть несколько вариантов.

  1. Добавьте вычесть значения, чтобы получить среднее число
  2. Добавьте полпикселя, чтобы уменьшить ошибку и, надеюсь, решить проблему (добавляйте полпикселя только к числам, оканчивающимся на x.3333...)

Примеры:

  1. flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
  2. flex-basis: calc(8/12 * 100% - (7/6 - 8/12) * 24px);

Я пошел с первым примером, чтобы дать мне этот повторяющийся код:

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 550px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^ = "col"] {
  border: 2px solid red;
}

.col-12 {
    flex-basis: calc(12/12 * 100% - (7/6 - 12/12) * 24px);
}
.col-11 {
    flex-basis: calc((11/12 - 1/6/100) * 100% - (7/6 - 11/12) * 24px);
}
.col-10 {
    flex-basis: calc((10/12 + 1/6/100) * 100% - (7/6 - 10/12) * 24px);
}
.col-9 {
    flex-basis: calc(9/12 * 100% - (7/6 - 9/12) * 24px);
}
.col-8 {
    flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
}
.col-7 {
    flex-basis: calc((7/12 + 1/6/100) * 100% - (7/6 - 7/12) * 24px);
}
.col-6 {
    flex-basis: calc(6/12 * 100% - (7/6 - 6/12) * 24px);
}
.col-5 {
    flex-basis: calc((5/12 - 1/6/100) * 100% - (7/6 - 5/12) * 24px);
}
.col-4 {
    flex-basis: calc((4/12 + 1/6/100) * 100% - (7/6 - 4/12) * 24px);
}
.col-3 {
    flex-basis: calc(3/12 * 100% - (7/6 - 3/12) * 24px);
}
.col-2 {
    flex-basis: calc((2/12 - 1/6/100) * 100% - (7/6 - 2/12) * 24px);
}
.col-1 {
    flex-basis: calc((1/12 + 1/6/100) * 100% - (7/6 - 1/12) * 24px);
}
<div class = "row">
  <div class = "col-12">col-12</div>
  <div class = "col-6">col-6</div>
  <div class = "col-6">col-6</div>
  <div class = "col-4">col-4</div>
  <div class = "col-4">col-4</div>
  <div class = "col-4">col-4</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-6">col-6</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-3">col-3</div>
  <div class = "col-4">col-4</div>
  <div class = "col-8">col-8</div>
  <div class = "col-7">col-7</div>
  <div class = "col-5">col-5</div>
  <div class = "col-6">col-6</div>
  <div class = "col-4">col-4</div>
  <div class = "col-2">col-2</div>
</div>

Это должно сработать в современных и даже самых старых браузерах, поддерживающих неокругленные calc

Если вы хотите увидеть второе решение, просто оставьте комментарий, и я опубликую его.

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

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