
在现代web开发中,创建响应式且用户友好的界面至关重要。有时,我们需要根据用户交互或屏幕尺寸动态调整元素的布局。本教程将深入探讨如何使用css flexbox和javascript,实现一个容器的垂直/水平布局切换,并在此过程中同步重排其内部的文本输入框。
核心概念:Flexbox与DOM操作
本方案的核心在于Flexbox布局模型及其在不同flex-direction下的行为,以及通过JavaScript动态修改元素的CSS属性。
-
Flexbox (display: flex): 强大的CSS布局模块,用于在一维空间内(行或列)排列和对齐元素。
- flex-direction: 定义主轴方向(row为水平,column为垂直)。
- flex: 定义弹性项目在主轴上的伸缩能力。
- flex-wrap: 控制弹性项目是否换行。
- JavaScript DOM操作: 通过JavaScript获取HTML元素,并修改其样式属性,以实现动态布局效果。
HTML结构
为了实现对输入框的精细控制,我们需要对原始HTML结构进行优化,将输入框进行分组。
动态Flexbox布局与嵌套元素重排
结构说明:
- container:最外层容器,其flex-direction将由JavaScript控制,决定整体布局是垂直还是水平。
- top:顶部区域,包含实际的输入框。它本身也是一个Flex容器,用于管理其子元素(即textbox-row)。
- textbox-row:新增的div元素,用于将输入框进行分组(例如,每4个输入框一组)。这个分组是实现内部输入框重排的关键,因为我们将通过JavaScript动态修改它的display属性。
- input[type="text"]:具体的文本输入框。
- toggle-switch 和 label:用于触发布局切换的UI元素。
CSS样式
CSS负责定义元素的初始布局、外观以及在不同状态下的表现。
/* 主容器样式 */
.container {
display: flex; /* 默认使用Flexbox */
flex-direction: column; /* 默认垂直布局 */
height: 100vh; /* 占据整个视口高度 */
}
/* 顶部和底部区域样式 */
.top {
flex: 3; /* 占据3份空间 */
background-color: blue;
border: 1px solid black;
display: flex; /* 内部也是Flex容器 */
flex-wrap: wrap; /* 允许子元素换行 */
align-items: center; /* 垂直居中对齐子元素 */
justify-content: center; /* 水平居中对齐子元素 */
}
.bottom {
flex: 7; /* 占据7份空间 */
background-color: green;
border: 1px solid black;
}
/* 输入框组样式 */
.textbox-row {
display: flex; /* 默认内部输入框水平排列 */
flex-wrap: wrap; /* 允许内部输入框换行 */
margin: 5px; /* 组间距 */
}
/* 输入框样式 */
.textbox-row input[type="text"] {
margin: 5px; /* 输入框间距 */
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
/* 切换开关的隐藏样式 */
input[type="checkbox"] {
height: 0;
width: 0;
visibility: hidden;
}
/* 切换开关的可见部分样式 */
label {
cursor: pointer;
text-indent: -9999px;
width: 50px;
height: 25px;
background-color: grey;
display: block;
border-radius: 100px;
position: relative;
margin: 10px; /* 调整位置 */
}
label:before {
content: "";
position: absolute;
top: 1px;
left: 1px;
width: 23px;
height: 23px;
background-color: #fff;
border-radius: 90px;
transition: 0.3s;
}
input:checked + label:before {
left: calc(100% - 1px);
transform: translateX(-100%);
}
/* 响应式设计:当屏幕宽度大于768px时 */
@media screen and (min-width: 768px) {
.container {
flex-direction: row; /* 默认主容器变为水平布局 */
}
.textbox-row {
display: block; /* 在大屏幕下,输入框组默认垂直堆叠 */
}
.textbox-row input[type="text"] {
margin: 0 5px 0 0; /* 调整输入框在大屏幕下的间距 */
}
/* 覆盖原始的input[type="text"] margin-bottom */
input[type="text"] {
margin-bottom: 0;
}
}CSS说明:
- .container:默认flex-direction: column,实现垂直堆叠布局。
- .top:内部的textbox-row元素将根据其父容器(.top)的Flex行为和自身的display属性进行排列。flex-wrap: wrap允许textbox-row在水平空间不足时换行。
- .textbox-row:默认display: flex; flex-wrap: wrap;,这意味着它内部的输入框会水平排列并自动换行。
- 媒体查询 (@media):在屏幕宽度大于768px时,.container默认变为flex-direction: row(水平布局),并且.textbox-row的display属性被设置为block。这意味着在宽屏下,默认情况下textbox-row组会垂直堆叠,而组内的输入框则根据其自身的流式布局(通常是内联并自动换行)。
JavaScript逻辑
JavaScript函数toggleDivs()负责监听切换开关的点击事件,并根据当前布局状态动态修改container和textbox-row的样式。
function toggleDivs() {
var container = document.querySelector(".container");
var top = document.querySelector(".top");
var bottom = document.querySelector(".bottom");
var textboxRows = document.querySelectorAll(".textbox-row"); // 获取所有输入框组
// 判断当前主容器是否为垂直布局
if (container.style.flexDirection === "column") {
// 切换到水平布局
container.style.flexDirection = "row";
top.style.flex = "3";
bottom.style.flex = "7";
top.style.height = "auto";
bottom.style.height = "auto";
// 当主容器为水平布局时,让每个textbox-row内部的输入框水平排列
textboxRows.forEach((row) => {
row.style.display = "flex"; // 设置为flex,内部输入框水平排列
});
} else {
// 切换到垂直布局
container.style.flexDirection = "column";
top.style.flex = "3";
bottom.style.flex = "7";
top.style.height = "100%";
bottom.style.height = "100%";
// 当主容器为垂直布局时,让每个textbox-row自身垂直堆叠
textboxRows.forEach((row) => {
row.style.display = "block"; // 设置为block,使每个textbox-row占据一行并垂直堆叠
});
}
}JavaScript说明:
- 获取元素:函数首先获取container、top、bottom以及所有的textbox-row元素。
- 判断当前布局:通过检查container.style.flexDirection的当前值来确定容器是垂直(column)










