Добавить стиль последнему элементу строки грид

Как добавить border-radius последним элементам (синему и серому) строк грид сетки, наподобие первых элементов? Желательно без js

https://codepen.io/ck1e/pen/VwmGoLZ

.colors {
  width: 320px;
  display: grid;
  grid-template-columns: repeat(auto-fit, 60px);
  grid-auto-rows: 40px;
  overflow: hidden;
  border-radius: 12px;
}

.color:nth-child(1) {
  background-color: red;
}

.color:nth-child(2) {
  background-color: #272729;
}

.color:nth-child(3) {
  background-color: #C71F2D;
}

.color:nth-child(4) {
  background-color: #FAE03C;
}

.color:nth-child(5) {
  background-color: #1F5DA0;
}

.color:nth-child(6) {
  background-color: #F96714;
}

.color:nth-child(7) {
  background-color: #00A28A;
}

.color:nth-child(8) {
  background-color: #58C9D4;
}

.color:nth-child(9) {
  background-color: #E1E1E1;
}

.color:last-child {
  border-radius: 0px 0px 12px 0px;
}
<div class="colors">
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
</div>


Ответы (3 шт):

Автор решения: webDev_

Сменить width на ширину совокупности всех элементов:

.colors
    width: calc(5 * 60px)

Если последний принципиален, даже если он не совпадает с верхним (как видно по ссылке), то ещё и:

.color
    &:last-child
         border-radius: 0px 0px 12px 0px
→ Ссылка
Автор решения: Sevastopol'

Как добавить border-radius последним элементам (синему и серому) строк грид сетки, наподобие первых элементов? Желательно без js

С помощь только Grid CSS - никак.


Предлагаю следующий вариант, с помощью JavaScript. Что мы делаем?

  1. Получаем ширину окна;
  2. Полученную ширину делим на ширину одного элемента, т.е. на 60px;
  3. Полученное число округляем до целого. Тем самым получаем количество элементов в одной строке. Округляем обязательно в меньшую сторону, чтобы ширина родительского элемента совпадала с общей шириной элементов в одной строке, потому как для родительского элемента в CSS установлено свойство border-radius: 12px и оно должно работать. Впрочем, в этом и заключается весь смысл всех манипуляций - динамически обернуть все дочерние элементы родительским элементом, исключив пустое пространство;
  4. Умножаем полученное количество элементов на ширину одного элемента, т.е. на 60px, и получаем ширину родительского элемента.
  5. устанавливаем родительскому элементу полученную ширину. В CSS предварительно свойство width удаляем.

Код расписан по шагам:

//Узнаем ширину окна
const pageWidth = document.documentElement.scrollWidth;
console.log('Ширина окна:', pageWidth, 'px');

//Ширину окна делим на ширину элемента (60px)
const drobWidth = pageWidth / 60
console.log('Ширину поделили на 60px:', drobWidth, 'px');

//Округляем до целого числа и получаем количество элементов в одной строке
const splitWidth = parseInt(((drobWidth + "").split("."))[0], 10);
console.log('Округлили до целого числа:', splitWidth, 'элементов по 60px');

//Умножаем количество полученных элементов на ширину одного элемента и получаем ширину родительского элемента
const colorsWidth = splitWidth * 60
console.log('Ширина родительского элемента:', colorsWidth, 'px');

//Устанавливаем ширину родительскому элементу
document.querySelector('.colors').style.width = colorsWidth + 'px';
* {
  margin: 0;
}

.colors {
  /*width: 320px;*/
  display: grid;
  grid-template-columns: repeat(auto-fit, 60px);
  grid-auto-rows: 40px;
  overflow: hidden;
  border-radius: 12px !important;
}

.color:nth-child(1) {
  background-color: red;
}

.color:nth-child(2) {
  background-color: #272729;
}

.color:nth-child(3) {
  background-color: #C71F2D;
}

.color:nth-child(4) {
  background-color: #FAE03C;
}

.color:nth-child(5) {
  background-color: #1F5DA0;
}

.color:nth-child(6) {
  background-color: #F96714;
}

.color:nth-child(7) {
  background-color: #00A28A;
}

.color:nth-child(8) {
  background-color: #58C9D4;
}

.color:nth-child(9) {
  background-color: #E1E1E1;
}

.color:nth-child(10) {
  background-color: green;
}

.color:nth-child(11) {
  background-color: gold;
}

.color:nth-child(12) {
  background-color: black;
}

.color:nth-child(13) {
  background-color: bisque;
}

.color:nth-child(14) {
  background-color: blue;
}

.color:last-child {
  border-radius: 0 0 12px 0;
}
<div class="colors">
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
</div>

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

Если элементов равное количество в каждой строке, и они одинаково распределяются:

//Узнаем ширину окна
const pageWidth = document.documentElement.scrollWidth;
//console.log('Ширина окна:', pageWidth, 'px');

//Ширину окна делим на ширину элемента (60px)
const drobWidth = pageWidth / 60
//console.log('Ширину поделили на 60px:', drobWidth, 'px');

//Округляем до целого числа и получаем количество элементов в одной строке
const splitWidth = parseInt(((drobWidth + "").split("."))[0], 10);
//console.log('Округлили до целого числа:', splitWidth, 'элементов по 60px');

//Умножаем количество полученных элементов на ширину одного элемента и получаем ширину родительского элемента
const colorsWidth = splitWidth * 60
//console.log('Ширина родительского элемента:', colorsWidth, 'px');

//Устанавливаем ширину родительскому элементу
document.querySelector('.colors').style.width = colorsWidth + 'px';


//Узнаем общее количество элементов
const elements = document.getElementsByClassName('color').length;
//console.log('Общее количество элементов:', elements);

//Узнаем возможное количество элементов в одной полностью заполненной элементами строке
const elems = colorsWidth / 60
console.log('Возможное кол-во элементов в одной полностью заполненной элементами строке:', elems);

//Узнаем количество полностью заполненных строк элементами
const lines = parseInt(((elements * 60 / colorsWidth + "").split("."))[0], 10);
console.log('Количество полностью заполненных строк элементами:', lines);

//Узнаем общую ширину всех элементов
const elementsWidth = elements * 60
//console.log('Общая ширина всех элементов:', elementsWidth, 'px');

//Узнаем количество элементов во всех полностью заполненных строках
const elems_lines = elems * lines
console.log('Количество элементов во всех полностью заполненных строках:', elems_lines);

//Условия:
//Если элементов больше, чем помещается в одну строку, то:
if (elementsWidth > elems * 60) {

  //Узнаем количество элементов (в остатке), в случае если есть дополнительные не полностью заполненные строки элементами
  if (elements > elems_lines) {
    const els = (elementsWidth - (lines * colorsWidth)) / 60
    console.log('Количество элементов в остатке:', els);
  };

  //Если есть, то последнему такому элементу добавляем дополнительный класс, чтобы скруглить правый нижний угол
  if (elements > elems_lines) {
    console.log('Есть ли не полностью заполненные строки элементами?:', 'Да');
    var list = document.querySelector('.colors')
    var item = list.getElementsByClassName('color')[elems_lines - 1];
    item.classList.add("border_bottom_right_radius");
  };
  //Если нет, то ничего не делаем
  if (elements <= elems_lines) {
    console.log('Есть ли дополнительные не полностью заполненные строки элементами?:', 'Нет');
  }

  //Если элементов меньше, чем помещается в одну строку, то последнему элементу добавляем класс, чтобы скруглить дополнительно еще и правый верхний угол
} else {
  var list = document.querySelector('.colors')
  var item = list.getElementsByClassName('color')[elements - 1];
  item.classList.add("border_top_right_radius");
};
* {
  margin: 0;
  padding: 0;
}

.colors {
  /*width: 320px;*/
  display: grid;
  grid-template-columns: repeat(auto-fit, 60px);
  grid-auto-rows: 40px;
  overflow: hidden;
  border-radius: 12px !important;
  color: white;
  text-align: center;
  line-height: 2.5;
}

.color:nth-child(odd) {
  background-color: red;
}

.color:nth-child(even) {
  background-color: green;
}

.color:last-child {
  border-radius: 0 0 12px 0;
}

.border_bottom_right_radius {
  border-radius: 0 0 12px 0;
  background-color: yellowgreen!important;
}

.border_top_right_radius {
  border-radius: 0 12px 12px 0 !important;
  background-color: yellowgreen!important;
}
<div class="colors">
  <div class="color">1</div>
  <div class="color">2</div>
  <div class="color">3</div>
  <div class="color">4</div>
  <div class="color">5</div>
  <div class="color">6</div>
  <div class="color">7</div>
  <div class="color">8</div>
  <div class="color">9</div>
  <div class="color">10</div>
  <div class="color">11</div>
  <div class="color">12</div>
  <div class="color">13</div>
  <div class="color">14</div>
  <div class="color">15</div>
  <div class="color">16</div>
  <div class="color">17</div>
  <div class="color">18</div>
  <div class="color">19</div>
  <div class="color">20</div>
</div>

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

//Узнаем ширину окна
const pageWidth = document.documentElement.scrollWidth;
//console.log('Ширина окна:', pageWidth, 'px');

//Ширину окна делим на ширину элемента (60px)
const drobWidth = pageWidth / 60
//console.log('Ширину поделили на 60px:', drobWidth, 'px');

//Округляем до целого числа и получаем количество элементов в одной строке
const splitWidth = parseInt(((drobWidth + "").split("."))[0], 10);
//console.log('Округлили до целого числа:', splitWidth, 'элементов по 60px');

//Умножаем количество полученных элементов на ширину одного элемента и получаем ширину родительского элемента
const colorsWidth = splitWidth * 60
//console.log('Ширина родительского элемента:', colorsWidth, 'px');

//Устанавливаем ширину родительскому элементу
document.querySelector('.colors').style.width = colorsWidth + 'px';


//Узнаем общее количество элементов
const elements = document.getElementsByClassName('color').length;
//console.log('Общее количество элементов:', elements);

//Узнаем возможное количество элементов в одной полностью заполненной элементами строке
const elems = colorsWidth / 60
//console.log('Возможное кол-во элементов в одной полностью заполненной элементами строке:', elems);

//Узнаем количество полностью заполненных строк элементами
const lines = parseInt(((elements * 60 / colorsWidth + "").split("."))[0], 10);
console.log('Количество полностью заполненных строк элементами:', lines);

//Узнаем общую ширину всех элементов
const elementsWidth = elements * 60
//console.log('Общая ширина всех элементов:', elementsWidth, 'px');

//Узнаем количество элементов во всех полностью заполненных строках
const elems_lines = elems * lines
console.log('Количество элементов во всех полностью заполненных строках:', elems_lines);

//Условия:
//Если элементов больше, чем помещается в одну строку, то:
if (elementsWidth > elems * 60) {

  //Узнаем количество элементов (в остатке), в случае если есть дополнительные не полностью заполненные строки элементами
  if (elements > elems_lines) {
    const els = (elementsWidth - (lines * colorsWidth)) / 60
    console.log('Количество элементов в остатке:', els);
  };

  //Если есть, то последнему такому элементу добавляем дополнительный класс, чтобы скруглить правый нижний угол
  if (elements > elems_lines) {
    console.log('Есть ли не полностью заполненные строки элементами?:', 'Да');
    var list = document.querySelector('.colors')
    var item = list.getElementsByClassName('color')[elems_lines - 1];
    item.classList.add("border_bottom_right_radius");
  };
  //Если нет, то ничего не делаем
  if (elements <= elems_lines) {
    console.log('Есть ли дополнительные не полностью заполненные строки элементами?:', 'Нет');
  }

  //Если элементов меньше, чем помещается в одну строку, то последнему элементу добавляем класс, чтобы скруглить дополнительно еще и правый верхний угол
} else {
  var list = document.querySelector('.colors')
  var item = list.getElementsByClassName('color')[elements - 1];
  item.classList.add("border_top_right_radius");
};
* {
  margin: 0;
  padding: 0;
}

.colors {
  /*width: 320px;*/
  display: grid;
  grid-template-columns: repeat(auto-fit, 60px);
  grid-auto-rows: 40px;
  overflow: hidden;
  border-radius: 12px !important;
  color: white;
  text-align: center;
  line-height: 2.5;
}

.color:nth-child(odd) {
  background-color: red;
}

.color:nth-child(even) {
  background-color: green;
}

.color:last-child {
  border-radius: 0 0 12px 0;
}

.border_bottom_right_radius {
  border-radius: 0 0 12px 0;
  background-color: yellowgreen!important;
}

.border_top_right_radius {
  border-radius: 0 12px 12px 0 !important;
  background-color: yellowgreen!important;
}
<div class="colors">
  <div class="color">1</div>
  <div class="color">2</div>
  <div class="color">3</div>
  <div class="color">4</div>
  <div class="color">5</div>
  <div class="color">6</div>
  <div class="color">7</div>
  <div class="color">8</div>
  <div class="color">9</div>
  <div class="color">10</div>
  <div class="color">11</div>
  <div class="color">12</div>
  <div class="color">13</div>
  <div class="color">14</div>
  <div class="color">15</div>
  <div class="color">16</div>
  <div class="color">17</div>
</div>

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

//Узнаем ширину окна
const pageWidth = document.documentElement.scrollWidth;
//console.log('Ширина окна:', pageWidth, 'px');

//Ширину окна делим на ширину элемента (60px)
const drobWidth = pageWidth / 60
//console.log('Ширину поделили на 60px:', drobWidth, 'px');

//Округляем до целого числа и получаем количество элементов в одной строке
const splitWidth = parseInt(((drobWidth + "").split("."))[0], 10);
//console.log('Округлили до целого числа:', splitWidth, 'элементов по 60px');

//Умножаем количество полученных элементов на ширину одного элемента и получаем ширину родительского элемента
const colorsWidth = splitWidth * 60
//console.log('Ширина родительского элемента:', colorsWidth, 'px');

//Устанавливаем ширину родительскому элементу
document.querySelector('.colors').style.width = colorsWidth + 'px';


//Узнаем общее количество элементов
const elements = document.getElementsByClassName('color').length;
//console.log('Общее количество элементов:', elements);

//Узнаем возможное количество элементов в одной полностью заполненной элементами строке
const elems = colorsWidth / 60
console.log('Возможное кол-во элементов в одной полностью заполненной элементами строке:', elems);

//Узнаем количество полностью заполненных строк элементами
const lines = parseInt(((elements * 60 / colorsWidth + "").split("."))[0], 10);
console.log('Количество полностью заполненных строк элементами:', lines);

//Узнаем общую ширину всех элементов
const elementsWidth = elements * 60
//console.log('Общая ширина всех элементов:', elementsWidth, 'px');

//Узнаем количество элементов во всех полностью заполненных строках
const elems_lines = elems * lines
console.log('Количество элементов во всех полностью заполненных строках:', elems_lines);

//Условия:
//Если элементов больше, чем помещается в одну строку, то:
if (elementsWidth > elems * 60) {

  //Узнаем количество элементов (в остатке), в случае если есть дополнительные не полностью заполненные строки элементами
  if (elements > elems_lines) {
    const els = (elementsWidth - (lines * colorsWidth)) / 60
    console.log('Количество элементов в остатке:', els);
  };

  //Если есть, то последнему такому элементу добавляем дополнительный класс, чтобы скруглить правый нижний угол
  if (elements > elems_lines) {
    console.log('Есть ли не полностью заполненные строки элементами?:', 'Да');
    var list = document.querySelector('.colors')
    var item = list.getElementsByClassName('color')[elems_lines - 1];
    item.classList.add("border_bottom_right_radius");
  };
  //Если нет, то ничего не делаем
  if (elements <= elems_lines) {
    console.log('Есть ли дополнительные не полностью заполненные строки элементами?:', 'Нет');
  }

  //Если элементов меньше, чем помещается в одну строку, то последнему элементу добавляем класс, чтобы скруглить дополнительно еще и правый верхний угол
} else {
  var list = document.querySelector('.colors')
  var item = list.getElementsByClassName('color')[elements - 1];
  item.classList.add("border_top_right_radius");
};
* {
  margin: 0;
  padding: 0;
}

.colors {
  /*width: 320px;*/
  display: grid;
  grid-template-columns: repeat(auto-fit, 60px);
  grid-auto-rows: 40px;
  overflow: hidden;
  border-radius: 12px !important;
  color: white;
  text-align: center;
  line-height: 2.5;
}

.color:nth-child(odd) {
  background-color: red;
}

.color:nth-child(even) {
  background-color: green;
}

.color:last-child {
  border-radius: 0 0 12px 0;
}

.border_bottom_right_radius {
  border-radius: 0 0 12px 0;
  background-color: yellowgreen!important;
}

.border_top_right_radius {
  border-radius: 0 12px 12px 0 !important;
  background-color: yellowgreen!important;
}
<div class="colors">
  <div class="color">1</div>
  <div class="color">2</div>
  <div class="color">3</div>
  <div class="color">4</div>
  <div class="color">5</div>
</div>

→ Ссылка
Автор решения: ck1e

Вариант через перебор элементов: https://codepen.io/ck1e/pen/VwmGoLZ

const initBorderColors = function() {
  // Количество элементов в одной строке
  const quanEl = Math.floor(document.querySelector('.colors').scrollWidth / document.querySelector('.color').scrollWidth);

  document.querySelectorAll('.color').forEach(function(item, index, array) {
    // Если больше одной строки
    if (array.length / quanEl > 1) {
      // Добавляем радиусы последнему элементу первой строки
      array[quanEl - 1].classList.add("--border-r");
      // Если больше двух строк
      if (array.length / quanEl > 2) {
        // Добавляем радиусы последнему элементу первой строки
        array[array.length - array.length % quanEl - 1].classList.add("--border-br");
        // Добавляем радиусы последнему элементу предпоследней строки
        array[quanEl - 1].classList.add("--border-tr");
      }
    }
  });
}
window.addEventListener("load", initBorderColors)
.colors {
  display: flex;
  flex-wrap: wrap;
  max-width: max-content;
  overflow: hidden;
  border-radius: 12px;
}

.color {
  width: 60px;
  height: 40px;
}

@media (min-width: 992px) {
  .color {
    width: 38px;
    height: 44px;
  }
}

.color:last-child {
  border-radius: 0 0 12px 0;
  background-color: #fff;
}

.color:nth-child(2) {
  background-color: #272729;
}

.color:nth-child(3) {
  background-color: #C71F2D;
}

.color:nth-child(4) {
  background-color: #FAE03C;
}

.color:nth-child(5) {
  background-color: #1F5DA0;
}

.color:nth-child(6) {
  background-color: #F96714;
}

.color:nth-child(7) {
  background-color: #00A28A;
}

.color:nth-child(8) {
  background-color: #58C9D4;
}

.color:nth-child(9) {
  background-color: #E1E1E1;
}

.--border-r {
  border-radius: 0 12px 12px 0;
}

.--border-tr {
  border-radius: 0 12px 0 0;
}

.--border-br {
  border-radius: 0 0 12px 0;
}
<div class="colors">
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
  <div class="color"></div>
</div>

→ Ссылка