CSS переходящий поток контента - программирование

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

Есть ли способ определить поток контента в CSS, используя flex или другие методы, так что контент "зигзаги" или обходится таким образом:

 -----------------
|A > B > C > D > E|
|J < I < H < G < F|
 -----------------

 ---
|A H|
|B G|
|C F|
|D E|
 ---

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

Как мне сделать так, чтобы первая строка текла направо, а вторая - налево?

4b9b3361

Ответ 1

Следующее решение не использует JavaScript и несколько масштабируемо. Я использую display: flex чтобы я мог использовать свойство order.

Основная идея - назначить order: 1 последнему элементу, order: 2 второму последнему элементу и т.д. Первая половина элементов имеет order: -1 а order: -1 имеющий order: 0, используется в качестве разделителя. Сложная часть, где вы выясняете "первую половину" предметов:

.demo {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  background: #EEE;
}
.demo > * {
  margin: .5em;
  width: 4em;
  height: 4em;
  background: #0CF;
}

/*
 * the example work for a list of 20 elements
 * for additional elements extend the repeating selectors
 */

/* all items ordered backwards */

.demo > :nth-last-child(1)  { order: 1; }
.demo > :nth-last-child(2)  { order: 2; }
.demo > :nth-last-child(3)  { order: 3; }
.demo > :nth-last-child(4)  { order: 4; }
.demo > :nth-last-child(5)  { order: 5; }
.demo > :nth-last-child(6)  { order: 6; }
.demo > :nth-last-child(7)  { order: 7; }
.demo > :nth-last-child(8)  { order: 8; }
.demo > :nth-last-child(9)  { order: 9; }
.demo > :nth-last-child(10) { order: 10; }

/* first half items are source ordered */

.demo> :nth-child(-n+0):nth-last-child(n+1),
.demo> :nth-child(-n+1):nth-last-child(n+2),
.demo> :nth-child(-n+2):nth-last-child(n+3),
.demo> :nth-child(-n+3):nth-last-child(n+4),
.demo> :nth-child(-n+4):nth-last-child(n+5),
.demo> :nth-child(-n+5):nth-last-child(n+6),
.demo> :nth-child(-n+6):nth-last-child(n+7),
.demo> :nth-child(-n+7):nth-last-child(n+8),
.demo> :nth-child(-n+8):nth-last-child(n+9),
.demo> :nth-child(-n+9):nth-last-child(n+10),
.demo> :nth-child(-n+10):nth-last-child(n+11) {
  order: -1;
}

/* the separator uses flex-basis trick and ordered between the two halves */

.demo::after {
  content: "";
  flex-basis: 100%;
  order: 0;
}
<div class="demo">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
</div>

Ответ 2

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

Если мы предположим, что все элементы имеют одинаковую ширину, мы можем определить количество элементов в строке и применить стили к элементам в зависимости от строки.

Вот базовый пример, основанный на коде этого предыдущего ответа: fooobar.com/questions/15244807/...

//total number of element
var n_t = $('.item').length;
//full width of element with margin
var w = $('.item').outerWidth(true);
//width of container without padding
var w_c = $('.grid').width();
//nb element per row
var nb = Math.min(parseInt(w_c / w),n_t);
console.log(nb);
$('.item:nth-child(1n+'+(nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(2*nb+1)+')').removeClass('right');
$('.item:nth-child(1n+'+(3*nb+1)+')').addClass('right');
$('.item:nth-child(1n+'+(4*nb+1)+')').removeClass('right');

window.addEventListener('resize', function(event){
   //only the width of container will change
   w_c = $('.grid').width();
   nb = Math.min(parseInt(w_c / w),n_t);
   $('.item').removeClass('right');   
  $('.item:nth-child(1n+'+(nb+1)+')').addClass('right');
  $('.item:nth-child(1n+'+(2*nb+1)+')').removeClass('right');
  $('.item:nth-child(1n+'+(3*nb+1)+')').addClass('right');
  $('.item:nth-child(1n+'+(4*nb+1)+')').removeClass('right');
});
.grid {
  background-color: #ddd;
  padding: 10px 0 0 10px;
  overflow:hidden;
}

.item {
  width: 80px;
  height: 80px;
  float:left;
  clear:right;
  background-color: red;
  margin: 0 10px 10px 0;
}
.item.right {
  float:right;
  clear:left;
  background:blue;
}

body {
  margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
  <div class="item">A</div>
  <div class="item">B</div>
  <div class="item">C</div>
  <div class="item">D</div>
  <div class="item">E</div>
  <div class="item">F</div>
  <div class="item">G</div>
  <div class="item">H</div>
  <div class="item">I</div>
  <div class="item">J</div>
  <div class="item">K</div>
  <div class="item">L</div>
  <div class="item">M</div>
  <div class="item">N</div>
  <div class="item">O</div>
  <div class="item">P</div>
</div>

Ответ 3

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

Недостатком является то, что вам нужно будет определить множество правил, если вам нужно поддерживать много элементов.

.box{
  width: 160px;
}

.item{
  width: 40px;
  float: left;
}

/* selecting half or more items. Up to 6 */
.item:first-child:last-child,
.item:nth-child(n+2):nth-last-child(-n+2),
.item:nth-child(n+3):nth-last-child(-n+3),
.item:nth-child(n+4):nth-last-child(-n+4),
.item:nth-child(n+5):nth-last-child(-n+5),
.item:nth-child(n+6):nth-last-child(-n+6) {
  float: right;
}
<div class="box">
  <div class="item">A</div>
  <div class="item">B</div>
  <div class="item">C</div>
  <div class="item">D</div>
  <div class="item">E</div>
  <div class="item">F</div>
  <div class="item">G</div>
  <div class="item">H</div>
</div>

Ответ 4

Я смог сделать это с помощью Flexbox и немного JavaScript (я не мог сделать это только с помощью CSS):

var reverseBoxes = function () {

  var flexItems = document.querySelectorAll(".child"),
      flexItemsCount = flexItems.length,
      reverseAt = flexItems.length / 2,
      breakPoint = 480;

  for (var i = reverseAt; i < flexItemsCount; i++) {
    flexItems[i].style.order = flexItemsCount - i;
  }

  for (var j = 0; j < flexItemsCount; j++) {
    if (window.innerWidth > breakPoint) {
      flexItems[j].style.width = (100 / flexItemsCount) * 2 - 2 + "%";
      flexItems[j].style.height = "auto";
    } else {
      flexItems[j].style.height = (100 / flexItemsCount) * 2 - 2 + "%";
      flexItems[j].style.width = "auto";
    }
  }

}

reverseBoxes();
window.addEventListener("resize", reverseBoxes);
body {
  font-family: Arial, sans-serif;
  font-size: 18px;
  margin: 0;
  padding: 0;
}

.parent {
  display: flex;
  flex-wrap: wrap;
  list-style-type: none;
  padding: 0;
  height: 100vh;
}

.child {
  margin: 1%;
  text-align: center;
  background: #069;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media only screen and (max-width: 480px) {
  .parent {
    flex-direction: column;
  }
  .child {
    width: 48%;
  }
}
<div class="parent">
  <div class="child">A</div>
  <div class="child">B</div>
  <div class="child">C</div>
  <div class="child">D</div>
  <div class="child">E</div>
  <div class="child">F</div>
  <div class="child">G</div>
  <div class="child">H</div>
  <div class="child">I</div>
  <div class="child">J</div>
</div>