咖啡喝完没,喝完了,我们就继续看看后面后面布局 除了有传统的线性布局(从上到下 从左到右这种)还有一些特殊的布局 ,前端中还有相对布局 绝对布局 固定布局,响应式页面布局,在鸿蒙中都对应的是什么?
相对定位+绝对定位
一个父容器里面有一个子元素 在父元素的右下架
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
position: relative; /* 成为子元素绝对定位的参照物 */
width: 300px;
height: 200px;
border: 1px solid gray;
}
.absolute-child {
position: absolute;
bottom: 10px; /* 相对于 container 底部定位 */
right: 10px; /* 相对于 container 右侧定位 */
background: gold;
}
</style>
</head>
<body>
<div class="container">
<div class="absolute-child">右下角按钮</div>
</div>
</body>
</html>
效果
编辑
鸿蒙中贼简单 使用position就可以了
Column() {
Text("右下角按钮").backgroundColor(Color.Yellow)
.position({ //位置相对父元素的位置 默认在左上角(0,0)
right:10,
bottom:10
})
}
.height(200)
.width(300)
.border({
width:2,
color:Color.Gray,
style:BorderStyle.Solid
})
效果:
编辑
也可以用 RelativeContainer,用的里面的子元素参考父元素的位置,参考物叫做锚点(anchor后面的目标 相对子元素可以id 用id名称就可以了 )
@Entry
@Component
struct Three {
build() {
RelativeContainer() {
Text("右下角按钮").backgroundColor(Color.Yellow).alignRules({
right:{anchor:"__container__",align:HorizontalAlign.End},
bottom:{anchor:"__container__",align:VerticalAlign.Bottom}
}).offset({
top:-10,
right:10
})
}
.height(200)
.width(300)
.border({
width:2,
color:Color.Gray,
style:BorderStyle.Solid
})
}
}
编辑
固定布局
场景页面有滚动条,滚动的时候有元素固定在页面的左边 不收到影响
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.fixed-sidebar {
position: fixed;
top: 100px;
right: 20px;
width: 200px;
border: 1px solid #ddd;
padding: 10px;
}
/* 在固定容器内使用相对定位微调元素 */
.highlight {
position: relative; /* 相对于父容器定位 */
left: -15px; /* 向左偏移 */
background: yellow;
padding: 5px;
}
</style>
</head>
<body>
<div class="fixed-sidebar">
<h3>侧边栏</h3>
<div class="highlight">特惠内容 ← 相对定位微调</div>
<p>其他信息...</p>
</div>
<div style="height: 2000px;">滚动页面,侧边栏位置不变</div>
</body>
</html>
效果如下
编辑
鸿蒙中是实现的方式就就没有关键了 依然使用RelativeContainer
@Entry
@Component
struct Four {
build() {
RelativeContainer() {
Column(){//悬浮框所在位置
Text("特惠内容 ← 相对定位微调")
}.width(100).height(100).border({
width:2,
color:Color.Gray,
style:BorderStyle.Solid
}).alignRules({
right:{
anchor:"__container__",align:HorizontalAlign.End
}
}).offset({
right:10
})
List(){
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
}.alignRules({//在父元素的左上角开始
left:{anchor:"__container__",align:HorizontalAlign.Start},
top:{anchor:"__container__",align:VerticalAlign.Top}
})
}
.height('100%')
.width('100%')
}
}
效果如图
编辑
用鸿蒙中层叠布局也可以实现
@Entry
@Component
struct Four {
build() {
Stack({alignContent:Alignment.TopEnd}) { //全部在右上角显示
//top表示锤子方向上 End表示水平方向结束的地方
Column(){//悬浮框所在位置
Text("特惠内容 ← 相对定位微调")
}.width(100).height(100).border({
width:2,
color:Color.Gray,
style:BorderStyle.Solid
}).offset({
right:10
})
List(){//容器宽度需要变成100% 不然都回去父元素左边
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
ListItem(){
Text("滚动页面, 特惠内容不变")
}.height(300)
}.width("100%")
}
.height('100%')
.width('100%')
}
}
响应式页面布局
前端中常用媒体查询来做 需求
三种设备宽度 大屏幕 一行显示四个内容块, 中屏幕显示一行显示两个内容块, 小屏幕一行显示一个内容库,内容块的颜色不一样
需求的效果
大宽度屏幕
编辑
中宽度屏幕
编辑
小宽度屏幕
编辑
前端完整代码 有点多
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式内容块布局</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
color: #333;
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
padding: 30px 0;
margin-bottom: 40px;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
h1 {
font-size: 2.8rem;
color: #1a2a6c;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
}
.subtitle {
font-size: 1.4rem;
color: #555;
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
.device-indicator {
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 12px 20px;
border-radius: 30px;
display: inline-block;
margin-top: 20px;
font-weight: bold;
font-size: 1.2rem;
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}
.blocks-container {
display: flex;
flex-wrap: wrap;
gap: 25px;
justify-content: center;
margin-bottom: 40px;
}
.block {
background: linear-gradient(135deg, #3498db, #2980b9);
border-radius: 12px;
padding: 30px;
text-align: center;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
flex: 1 1 calc(25% - 25px);
min-width: 250px;
color: white;
}
.block:hover {
transform: translateY(-10px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
}
.block h3 {
font-size: 1.8rem;
margin-bottom: 15px;
}
.block p {
font-size: 1.1rem;
line-height: 1.6;
}
.block-icon {
font-size: 3.5rem;
margin-bottom: 20px;
color: rgba(255, 255, 255, 0.9);
}
.info-section {
background: rgba(255, 255, 255, 0.9);
padding: 30px;
border-radius: 15px;
margin-top: 40px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.info-section h2 {
color: #1a2a6c;
margin-bottom: 20px;
text-align: center;
font-size: 2rem;
}
.media-query-info {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 20px;
}
.device-info {
background: white;
padding: 25px;
border-radius: 10px;
flex: 1;
min-width: 300px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.device-info h3 {
font-size: 1.5rem;
color: #1a2a6c;
margin-bottom: 15px;
text-align: center;
}
.device-info ul {
padding-left: 20px;
}
.device-info li {
margin-bottom: 10px;
font-size: 1.1rem;
line-height: 1.5;
}
/* 大屏幕样式 (≥1200px) - 一行4个块 */
@media (min-width: 1200px) {
.block {
background: linear-gradient(135deg, #3498db, #2980b9);
flex: 1 1 calc(25% - 25px);
}
.device-indicator::after {
content: "大屏幕 (≥1200px)";
background: #3498db;
}
}
/* 中屏幕样式 (768px - 1199px) - 一行2个块 */
@media (min-width: 768px) and (max-width: 1199px) {
.block {
background: linear-gradient(135deg, #2ecc71, #27ae60);
flex: 1 1 calc(50% - 25px);
}
.device-indicator::after {
content: "中屏幕 (768px - 1199px)";
background: #2ecc71;
}
}
/* 小屏幕样式 (<768px) - 一行1个块 */
@media (max-width: 767px) {
.block {
background: linear-gradient(135deg, #e74c3c, #c0392b);
flex: 1 1 100%;
}
h1 {
font-size: 2.2rem;
}
.subtitle {
font-size: 1.2rem;
}
.device-indicator::after {
content: "小屏幕 (<768px)";
background: #e74c3c;
}
}
.device-indicator::after {
padding: 8px 20px;
border-radius: 20px;
display: block;
color: white;
font-weight: bold;
}
footer {
text-align: center;
color: white;
padding: 20px;
margin-top: 40px;
font-size: 1.1rem;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>响应式内容块布局</h1>
<p class="subtitle">使用CSS媒体查询根据不同设备宽度显示不同数量和颜色的内容块。调整浏览器窗口大小查看效果变化。</p>
<div class="device-indicator"></div>
</header>
<div class="blocks-container">
<div class="block">
<div class="block-icon">📱</div>
<h3>响应式设计</h3>
<p>确保网站在各种设备上都能提供良好的用户体验,无论屏幕大小如何。</p>
</div>
<div class="block">
<div class="block-icon">💻</div>
<h3>媒体查询</h3>
<p>使用@media规则根据设备特性应用不同的CSS样式,实现布局变化。</p>
</div>
<div class="block">
<div class="block-icon">📐</div>
<h3>弹性布局</h3>
<p>通过Flexbox或Grid实现灵活的布局结构,适应不同屏幕尺寸。</p>
</div>
<div class="block">
<div class="block-icon">🌈</div>
<h3>视觉反馈</h3>
<p>在不同设备上使用不同颜色方案,提供清晰的视觉指示。</p>
</div>
<div class="block">
<div class="block-icon">⚙️</div>
<h3>性能优化</h3>
<p>针对不同设备优化资源加载,提升页面加载速度。</p>
</div>
<div class="block">
<div class="block-icon">👆</div>
<h3>触摸友好</h3>
<p>为移动设备设计更大的触摸目标和合适的手势支持。</p>
</div>
<div class="block">
<div class="block-icon">🔍</div>
<h3>可读性</h3>
<p>在小屏幕上调整字体大小和行高,确保内容易于阅读。</p>
</div>
<div class="block">
<div class="block-icon">🚀</div>
<h3>现代技术</h3>
<p>使用CSS变量、Grid布局等现代技术简化响应式开发。</p>
</div>
</div>
<div class="info-section">
<h2>媒体查询实现方式</h2>
<div class="media-query-info">
<div class="device-info">
<h3>大屏幕 (≥1200px)</h3>
<ul>
<li>一行显示四个内容块</li>
<li>内容块背景:蓝色渐变</li>
<li>使用CSS: <code>@media (min-width: 1200px) { ... }</code></li>
<li>适合桌面电脑和大尺寸显示器</li>
<li>内容块宽度:约25%</li>
</ul>
</div>
<div class="device-info">
<h3>中屏幕 (768px - 1199px)</h3>
<ul>
<li>一行显示两个内容块</li>
<li>内容块背景:绿色渐变</li>
<li>使用CSS: <code>@media (min-width: 768px) and (max-width: 1199px) { ... }</code></li>
<li>适合平板电脑和小型笔记本</li>
<li>内容块宽度:约50%</li>
</ul>
</div>
<div class="device-info">
<h3>小屏幕 (<768px)</h3>
<ul>
<li>一行显示一个内容块</li>
<li>内容块背景:红色渐变</li>
<li>使用CSS: <code>@media (max-width: 767px) { ... }</code></li>
<li>适合手机等移动设备</li>
<li>内容块宽度:100%</li>
</ul>
</div>
</div>
</div>
</div>
<footer>
<p>响应式设计示例 © 2023 | 调整浏览器窗口大小查看不同设备布局效果</p>
</footer>
</body>
</html>
在鸿蒙实现
@Component
@Entry
struct Five {
build() {
Column() {
GridRow({
columns: {//占比
xs: 1,//小屏幕中1表示全部
sm: 2,//中 2表示全部 1表示 1/2
md: 4//大 4表示全部 1表示1/4
},
gutter: 10,
breakpoints: {
value: ['320vp', '600vp', '840vp'],//三个范围
reference: BreakpointsReference.WindowSize
},
direction: GridRowDirection.Row
}) {
GridCol() {
Column().width('100%').height(100).backgroundColor(Color.Red)
}.span({
xs: 1,
sm: 1,
md: 1
})
GridCol() {
Column().width('100%').height(100).backgroundColor( Color.Yellow)
}.span({
xs: 1,
sm: 1,
md: 1
})
GridCol() {
Column().width('100%').height(100).backgroundColor( Color.Green)
}.span({
xs: 1,
sm: 1,
md: 1
})
GridCol() {
Column().width('100%').height(100).backgroundColor( Color.Blue)
}.span({
xs: 1,
sm: 1,
md: 1
})
}
.width('90%')
.backgroundColor(0xFAEEE0)
.padding({ top: 10, bottom: 10 })
}.width('100%')
}
}
效果
宽屏幕
编辑
中屏幕
编辑
小屏幕
编辑
响应式布局核心概念 特别重要
响应式布局(Responsive Design)是一种自适应的设计方法,使网页或应用能够根据用户的设备环境(系统、屏幕尺寸、方向等)自动调整布局和内容展示,提供最佳的用户体验。
核心原则:
- 流动网格:使用相对单位(如%、vw/vh)替代固定单位
- 弹性媒体:图片、视频等元素能随容器缩放
- 媒体查询:根据设备特性应用不同样式规则
- 移动优先:从小屏幕开始设计,逐步增强大屏体验
响应式布局关键要素
| 要素 | Web实现 | 鸿蒙ArkTS实现 | 说明 |
|---|---|---|---|
| 布局容器 | Flexbox/Grid | GridRow/GridCol | 创建灵活的布局结构 |
| 断点检测 | @media查询 | mediaQuery API | 检测设备特性变化 |
| 相对单位 | %、vw/vh | vp(虚拟像素) | 确保元素相对缩放 |
| 状态管理 | CSS变量 | @State装饰器 | 响应式更新UI |
| 组件复用 | CSS类 | @Builder方法 | 提高代码复用性 |
结论:响应式布局的核心价值
响应式布局不仅是技术方案,更是以用户为中心的设计哲学。它确保用户在任何设备上都能获得:
- 一致的内容体验 - 核心信息完整呈现
- 自然的交互方式 - 针对设备优化操作
- 高效的性能表现 - 按需加载资源
- 无缝的多屏切换 - 设备间体验连贯
随着设备形态的多样化(折叠屏、可穿戴设备等),响应式设计将成为数字产品的基础能力而非可选特性。
通过掌握响应式布局的核心原理和实现技术,开发者可以构建真正"一次开发,多端适配"的高质量应用体验。