是否有一种方法可以使用flex或其他技术在CSS中定义内容流,以使内容“曲折”或以这种方式出现:
-----------------
|A > B > C > D > E|
|J < I < H < G < F|
-----------------
---
|A H|
|B G|
|C F|
|D E|
---
假设总有2列或2行。我可以将项目拆分为2个,并在它们周围创建2个包装项目,但我希望它更具动态性。
基本上,如何使第一行向右流动而第二行向左流动?
答案 0 :(得分:2)
很明显,要实现这样的目标实际上并不存在纯粹的可扩展CSS解决方案,因此您将需要一些脚本来动态调整某些属性以获得所需的布局。
如果我们假设所有元素的宽度都相同,则可以确定每行元素的数量,并根据行的样式对元素应用样式。
这是基于此先前答案的代码的基本示例:https://stackoverflow.com/a/49046973/8620333
//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>
此示例不是一个完美的示例,因为我们在对齐方面存在问题,但其想法是通过交替的行将浮动属性应用于行。我只考虑了4行,但是我们可以使用如下所示的循环轻松地将其动态化:
//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);
for(var i=1;i<n_t;i++) {
if(i%2==1)
$('.item:nth-child(1n+'+(i*nb+1)+')').addClass('right');
else
$('.item:nth-child(1n+'+(i*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');
for(var i=1;i<n_t;i++) {
if(i%2==1)
$('.item:nth-child(1n+'+(i*nb+1)+')').addClass('right');
else
$('.item:nth-child(1n+'+(i*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>
要获得更好的对齐方式,我们可以考虑使用CSS网格或flexbox,但在这种情况下,我们需要调整元素的order属性。
使用CSS网格:
//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);
//nb rows
var nr = n_t / nb;
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
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);
nr = n_t / nb;
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
});
.grid {
background-color: #ddd;
display: grid;
grid-template-columns: repeat( auto-fit, 80px);
padding: 10px 0 0 10px;
}
.item {
height: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
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>
此方法可以更好地对齐,但是最后一行并不总是很好。
我们可以通过调整usgin grid-column
的最后一个元素来更正最后一行,如下所示:
//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);
//nb rows
var nr = Math.ceil(n_t / nb);
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
/*fix the last row*/
if (i == (nr - 1)) {
$('.item').eq(nb * i + j).css('grid-column', " " + (nb - j));
}
}
}
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);
nr = Math.ceil(n_t / nb);
$('.item').css('grid-column', 'auto');
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
/*fix the last row*/
if (i == nr - 1) {
$('.item').eq(nb * i + j).css('grid-column', " " + (nb - j));
}
}
}
});
.grid {
background-color: #ddd;
display: grid;
grid-template-columns: repeat( auto-fit, 80px);
grid-auto-flow: dense;
padding: 10px 0 0 10px;
}
.item {
height: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
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>
Flexbox可能更适合第二种情况(列方向)。我们只是在做与之前考虑使用列而不是行相同的操作:
//total number of element
var n_t = $('.item').length;
//full height of element with margin
var w = $('.item').outerHeight(true);
//height of container without padding
var w_c = $('.grid').height();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = n_t / nb;
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').height();
nb = Math.min(parseInt(w_c / w), n_t);
nr = n_t / nb;
or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
}
});
.grid {
display: flex;
height:100vh;
flex-direction:column;
flex-wrap:wrap;
align-items:flex-start;
align-content:flex-start;
padding-top: 10px;
padding-left:10px;
box-sizing:border-box;
}
.item {
height: 80px;
width:80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
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>
在某些情况下,我们可以通过调整边距来解决最后一列的对齐问题:
//total number of element
var n_t = $('.item').length;
//full height of element with margin
var w = $('.item').outerHeight(true);
//height of container without padding
var w_c = $('.grid').height();
//nb element per row
var nb = Math.min(parseInt(w_c / w), n_t);
//nb rows
var nr = Math.ceil(n_t / nb);
//order of element
var or = 0;
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else {
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
if (i == (nr - 1)) {
/*we add margin+height of non-existing element*/
$('.item:last').css('margin-top', ((nb * nr - n_t) * (80 + 10)) + "px")
}
}
}
window.addEventListener('resize', function(event) {
//only the width of container will change
w_c = $('.grid').height();
nb = Math.min(parseInt(w_c / w), n_t);
nr = Math.ceil(n_t / nb);
or = 0;
$('.item').css('margin-top', 0); /*reset the margin*/
for (var i = 0; i < nr; i++) {
if (i % 2 == 0)
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + j).css('order', or++);
}
else {
for (var j = 0; j < nb; j++) {
$('.item').eq(nb * i + (nb - j - 1)).css('order', or++);
}
if (i == (nr - 1)) {
/*we add margin+height of non-existing element*/
$('.item:last').css('margin-top', ((nb * nr - n_t) * (80 + 10)) + "px")
}
}
}
});
.grid {
display: flex;
height: 100vh;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
align-content: flex-start;
padding-top: 10px;
padding-left: 10px;
box-sizing: border-box;
}
.item {
height: 80px;
width: 80px;
background-color: red;
font-size: 30px;
color: #fff;
font-weight: bold;
margin: 0 10px 10px 0;
}
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>
答案 1 :(得分:2)
以下解决方案不使用JavaScript,并且具有一定的可扩展性。我使用display: flex
,以便可以使用order
属性。
基本思想是将order: 1
分配给最后一个项目,order: 2
分配给倒数第二个项目,依此类推。项目的前半部分具有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>
对于两列布局,请在父项上指定flex-direction: column; height: 25em
(高度必须固定)。
答案 2 :(得分:0)
这是一个技巧,可以帮助您选择一半的项目。默认使用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>
垂直情况可能是:
.box {
margin-top: 100px;
width: 160px;
transform: rotate(90deg);
}
.item {
width: 40px;
float: left;
transform: rotate(-90deg);
}
/* 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>
答案 3 :(得分:0)
我能够使用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>
您要寻找的是它吗?