使用CSS仅交换DIV位置

94

我想通过交换两个

的位置来实现响应式设计(网站在浏览器宽度不同时呈现不同的外观,更适合移动设备)。

目前我的代码大概是这样的:

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

但是只使用CSS,是否可以交换它们的位置,使其看起来像second_div在前面呢?HTML保持不变。我尝试使用浮动和其他方法,但它似乎不能按照我想要的方式工作。我不想使用绝对定位,因为

的高度总是在变化。有没有解决方案或者根本无法实现?


你是否担心IE8的兼容性问题?尝试使用媒体查询(http://caniuse.com/#feat=css-mediaqueries)。 - Mooseman
这是我目前用于响应式设计的工具,但是当它用于移动设备时,底部的div需要排在第一位。 - Dragonfly
1
这取决于div的当前布局。例如,如果first_div已经具有float: left,而second_div具有float: right,那么解决方案就非常简单 - 您只需要反转float的方向即可。其他布局将更难修复。请告诉我们当前的布局。 - Rory O'Kane
2022解决方案 - leonheess
11个回答

145

有人给我发了一个链接:什么是在响应式设计中将在顶部的元素移动到底部的最佳方法

那里提供的解决方案非常完美。虽然它不支持旧版IE,但这对我来说无所谓,因为我正在使用响应式设计进行移动。而且它适用于大多数移动浏览器。

基本上,我原来有这个:

@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;
  }
}

对我来说,这比浮动效果更好用,因为我需要它们堆叠在一起,并且我有大约五个不同的div需要交换位置。


5
这里是一个使用flexbox方法的示例 - blimmer
谢谢你提供的示例。我已经成功地编辑它以达到我的目标:http://jsfiddle.net/5rd9xwsc/73/ - Ryan
1
http://jsfiddle.net/5rd9xwsc/75/ 是我尝试做的更好的例子,即:当你调整窗口大小时,图像总是与文本交替显示。 - Ryan
1
我非常喜欢StackOverflow,我能够搜索我的活动并再次找到这篇文章。我更新了fiddle,因为http://jsfiddle.net/5rd9xwsc/82/更接近我想在WordPress中实现的内容。 - Ryan
提醒一下 - 这个解决方案乍一看可能会显得复杂或脆弱,但实际上它非常简单。厂商特定的样式是使其看起来“笨重”的原因。在我的使用情况中,我甚至不需要厂商特定的样式。感谢Dragonfly拯救了我! - Tell
如果first_div和second_div不是兄弟节点,它还能正常工作吗? - Akmal Salikhov

45

接受的答案适用于大多数浏览器,但由于某种原因,在iOS Chrome和Safari浏览器上应该显示第二个内容却被隐藏了。我尝试了一些其他步骤,强制内容堆叠在一起,最终我尝试了以下解决方案,在移动屏幕上切换内容显示顺序,达到了预期效果,没有堆叠或隐藏内容的错误:

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

.section1,
.section2 {
  height: auto;
}

34

虽然这个问题已经有了一个很好的答案,但是为了探索所有可能性,这里提供另一种重新排序 DOM 元素的技术,同时仍然允许它们占用其空间,不像绝对定位方法。

这种方法适用于所有现代浏览器和 IE9+(基本上支持 display:table 的任何浏览器),缺点是只能用于最多 3 个兄弟元素。

//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;
}

这将把元素从1、2、3重新排序为2、3、1。基本上,任何具有显示设置为table-header-group的内容都将位于顶部,而table-footer-group在底部。自然地,table-row-group将使一个元素处于中间位置。

使用此方法快速且得到良好支持,需要比flexbox方法少得多的CSS。因此,如果您只想为移动布局交换一些项目,则不要排除此技术。

您可以在codepen上查看实时演示:http://codepen.io/thepixelninja/pen/eZVgLx


width: 100% 这一行是无用的:你不能给 display: table 元素设置宽度。 - Clément
1
我的错。这不是我做的例子中的内容,可能是无意中进来了。但无论是否存在,该方法仍然有效。 :) - Ed Fryed
处理表单输入时,通常标签位于其上方,但在DOM中却位于其前面(因此我们可以基于输入状态来定位标签),这非常有帮助!同时也非常适用于浮动标签。 - Sơn Trần-Nguyễn
1
这是一种非常好的非弹性方式来实现它。即使在2019年,我们仍然有4%的IE9流量。 - secretwep

14

这个解决方案对我有用:

使用像这样的父元素:

.parent-div {
    display:flex;
    flex-direction: column-reverse;
}
在我的情况下,我不需要改变我需要切换的元素的CSS。

9

1
@Sarfaraj请确保您的flex:display处于活动状态,并且命令是ORDER而不是Flex-order。我曾经犯过这个错误。 - Sweet Chilly Philly

8

在这里输入图片描述

仅使用CSS:

#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>


5

假定它们之后没有其他元素

如果这两个div元素基本上是您的主要布局元素,并且在html中没有其他内容,那么有一种纯HMTL/CSS解决方案,可以像此示例所示按照正常顺序排列,并且可以使用一个额外的包装器div将其垂直翻转,例如:此示例

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%;
}

如果这些 div 后面跟着其他元素,这种方法就不会起作用,如这个 fiddle 展示了如果没有被包裹的后续元素(它们会被 #first_div 遮盖),这个 fiddle 展示了如果后续元素也被包裹的情况#first_div 会与 两个 #second_div后续元素交换位置)。因此,根据您的用例,这种方法可能有效也可能无效。 对于整体布局方案,所有其他元素都存在于这两个 div 中,这种方法可以起作用。 对于其他场景,这种方法则不可行。

4
简单的flexbox解决方案,利用order属性

.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>


1
这段代码对我有效。 - matinict
最好和最简单的解决方案 - undefined

1

你不需要任何花哨的东西。复制你的第二个 div,并将其放在顶部。就像这样

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

在编程中,当您想要第一个 div 显示在顶部时,请给 second_div_copy 显示:none。当您想要第二个 div 显示在顶部时,请给 second_div_copy 显示:block,并且 second_div 显示:none。
真的很简单。或者我漏掉了什么?

这是一篇8年前的帖子,所以有些事情自那时以来已经发生了变化。此外,他不想使用js添加新的div,而是希望在css中完成所有操作。 - Elikill58
很多事情都变了,但你还没有理解我的意思。 - Rob

1
假设两个元素都有50%的宽度,这是我使用的代码:
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>

例子:https://jsfiddle.net/gzveri/o6umhj53/

顺便说一下,这种方法适用于元素列表中任意相邻的两个元素。例如,我有一个由多个元素组成的长列表,每行有2个项目,我想要交换列表中的第3个和第4个元素,以便以棋盘样式呈现元素,则可以使用以下规则:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接