只用 CSS 交换 DIV 位置

我试图交换两个 div的位置响应设计(网站看起来不同取决于宽度的浏览器/良好的移动)。

现在我有这样的东西:

<div id="first_div"></div>
<div id="second_div"></div>

但是,是否有可能交换他们的位置,使它看起来像 second_div是第一,只使用 CSS?HTML 保持不变。我试过使用花车之类的东西,但它似乎没有按照我想要的方式工作。我不想使用绝对定位,因为 div的高度总是在变化。有什么解决办法吗,还是根本没有办法?

176705 次浏览

Someone linked me this: What is the best way to move an element that's on the top to the bottom in Responsive design.

The solution in that worked perfectly. Though it doesn’t support old IE, that doesn’t matter for me, since I’m using responsive design for mobile. And it works for most mobile browsers.

Basically, I had this:

@media (max-width: 30em) {
.container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
/* optional */
-webkit-box-align: start;
-moz-box-align: start;
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}


.container .first_div {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
-ms-flex-order: 2;
-webkit-order: 2;
order: 2;
}


.container .second_div {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
}

This worked better than floats for me, because I needed them stacked on top of each other and I had about five different divs that I had to swap around the position of.

Assuming Nothing Follows Them

If these two div elements are basically your main layout elements, and nothing follows them in the html, then there is a pure HMTL/CSS solution that takes the normal order shown in this fiddle and is able to flip it vertically as shown in this fiddle using one additional wrapper div like so:

HTML

<div class="wrapper flipit">
<div id="first_div">first div</div>
<div id="second_div">second div</div>
</div>

CSS

.flipit {
position: relative;
}
.flipit #first_div {
position: absolute;
top: 100%;
width: 100%;
}

This would not work if elements follow these div's, as this fiddle illustrates the issue if the following elements are not wrapped (they get overlapped by #first_div), and this fiddle illustrates the issue if the following elements are also wrapped (the #first_div changes position with both the #second_div and the following elements). So that is why, depending on your use case, this method may or may not work.

For an overall layout scheme, where all other elements exist inside the two div's, it can work. For other scenarios, it will not.

This question already has a great answer but in the spirit of exploring all possibilities here is another technique to reorder dom elements whilst still allowing them to take up their space, unlike the absolute positioning method.

This method works in all modern browsers and IE9+ (basically any browser that supports display:table) it has a drawback that it can only be used on a max of 3 siblings though.

//the html
<div class='container'>
<div class='div1'>1</div>
<div class='div2'>2</div>
<div class='div3'>3</div>
</div>


//the css
.container {
display:table;
}
.div1 {
display:table-footer-group;
}
.div2 {
display:table-header-group;
}
.div3 {
display:table-row-group;
}

This will reorder the elements from 1,2,3 to 2,3,1. Basically anything with the display set to table-header-group will be positioned at the top and table-footer-group at the bottom. Naturally table-row-group puts an element in the middle.

This method is quick with good support and requires much less css than the flexbox approach so if you are only looking to swap a few items around for a mobile layout for example then dont rule out this technique.

You can check out a live demo on codepen: http://codepen.io/thepixelninja/pen/eZVgLx

The accepted answer worked for most browsers but for some reason on iOS Chrome and Safari browsers the content that should have shown second was being hidden. I tried some other steps that forced content to stack on top of each other, and eventually I tried the following solution that gave me the intended effect (switch content display order on mobile screens), without bugs of stacked or hidden content:

.container {
display:flex;
flex-direction: column-reverse;
}


.section1,
.section2 {
height: auto;
}

enter image description here

Using CSS only:

#blockContainer {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}


#blockA {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
box-ordinal-group: 2;
}


#blockB {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
box-ordinal-group: 3;
}
<div id="blockContainer">
<div id="blockA">Block A</div>
<div id="blockB">Block B</div>
<div id="blockC">Block C</div>
</div>

In some cases you can just use the flex-box property order.

Very simple:

.flex-item {
order: 2;
}

See: https://css-tricks.com/almanac/properties/o/order/

This solution worked for me:

Using a parent element like:

.parent-div {
display:flex;
flex-direction: column-reverse;
}

In my case I didn't have to change the css of the elements that I needed to switch.

assuming both elements have 50% width, here is what i used:

css:

  .parent {
width: 100%;
display: flex;
}
.child-1 {
width: 50%;
margin-right: -50%;
margin-left: 50%;
background: #ff0;
}
.child-2 {
width: 50%;
margin-right: 50%;
margin-left: -50%;
background: #0f0;
}

html:

<div class="parent">
<div class="child-1">child1</div>
<div class="child-2">child2</div>
</div>

example: https://jsfiddle.net/gzveri/o6umhj53/

btw, this approach works for any 2 nearby elements in a long list of elements. For example I have a long list of elements with 2 items per row and I want each 3-rd and 4-th element in the list to be swapped, so that it renders elements in a chess style, then I use these rules:

  .parent > div:nth-child(4n+3) {
margin-right: -50%;
margin-left: 50%;
}
.parent > div:nth-child(4n+4) {
margin-right: 50%;
margin-left: -50%;
}

Yesterday ran into the same problem. Grid areas worked out great in my case:

.content-body {
display: grid;
grid-template-areas: " left right ";
grid-template-columns: 1fr 1fr;
}
.first_div {
grid-area: right;
}
.second {
grid-area: left;
}

You don't need anything fancy. Make a copy of your second div, and place it on top. Like this

<div id="second_div_copy"></div>
<div id="first_div"></div>
<div id="second_div"></div>

Give the second_div_copy display: none when you want first div to appear on top. Give the second_div_copy display: block, and the second_div display: none when you want the second div to appear on top.

It's really that simple. Or am I missing something ?

Simple flexbox solution utilizing the order-property:

.container {
display: flex;
flex-direction: column;
}


.first {
order: 3;
}


.second {
order: 2;
}
<div class="container">
<div class="first">First</div>
<div class="second">Second</div>
<div class="third">Third</div>
</div>