欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 前端Vue3项目响应式布局实战——基于Flex布局和媒体查询的响应式布局设计

前端Vue3项目响应式布局实战——基于Flex布局和媒体查询的响应式布局设计

2025/2/24 17:58:58 来源:https://blog.csdn.net/m0_55049655/article/details/144708858  浏览:    关键词:前端Vue3项目响应式布局实战——基于Flex布局和媒体查询的响应式布局设计

效果演示

Desktop端

在这里插入图片描述

iPad/Mobile端

在这里插入图片描述

Flex布局

Flexbox 布局总结

1. Flex 容器属性:
  • display:定义为 flex 容器。
  • flex-direction:主轴方向(行或列)。
  • flex-wrap:控制换行行为。
  • justify-content:主轴对齐方式(左右或上下)。
  • align-items:交叉轴对齐方式(纵向对齐)。
  • align-content:多行对齐方式(仅当有换行时有效)。
2. Flex 项目属性:
  • order改变项目的顺序
  • flex-grow:控制项目扩展。
  • flex-shrink:控制项目收缩。
  • flex-basis:定义项目的初始尺寸。
  • flexflex-growflex-shrinkflex-basis 的简写。
  • align-self:单个项目的交叉轴对齐。

Flex 布局属性总结

Flexbox(弹性盒子布局)提供了一套强大的布局工具,既适用于复杂的网页布局,又能处理响应式设计。其主要属性可以分为两类:

  • Flex 容器属性(控制容器的布局行为)
  • Flex 项目属性(控制容器内子元素的布局行为)
一、Flex 容器属性
  1. display

    • 定义容器的布局为 flexbox。
    • display: flex;display: inline-flex;(容器行为类似块级或行内元素)
    .container {display: flex;
    }
    
  2. flex-direction

    • 控制主轴(主方向)上项目的排列方向。
    • row(默认):水平,从左到右排列。
    • row-reverse:水平,从右到左排列。
    • column:垂直,从上到下排列。
    • column-reverse:垂直,从下到上排列。
    .container {flex-direction: row;
    }
    
  3. flex-wrap

    • 控制项目是否换行。
    • nowrap(默认):不换行,所有项目都在一行内。
    • wrap:换行,项目会换行并在多行中排列。
    • wrap-reverse:换行,但换行方向与 wrap 相反。
    .container {flex-wrap: wrap;
    }
    
  4. justify-content

    • 在主轴方向上对齐项目,控制项目之间的间隔。
    • flex-start(默认):项目靠容器的起始端对齐。
    • flex-end:项目靠容器的末尾对齐。
    • center:项目在主轴上居中对齐。
    • space-between:项目间的间隔相等,第一个项目靠近容器起始端,最后一个项目靠近容器末尾端。
    • space-around:项目之间的间隔相等,容器两侧的空白间隔也相等。
    • space-evenly:所有项目之间的间隔相等,包括容器两侧的空白。
    .container {justify-content: center;
    }
    
  5. align-items

    • 在交叉轴(垂直于主轴)上对齐项目。
    • flex-start:项目靠交叉轴起始端对齐。
    • flex-end:项目靠交叉轴末尾端对齐。
    • center:项目在交叉轴上居中对齐。
    • baseline:项目按文本基线对齐。
    • stretch(默认):项目拉伸以填充容器。
    .container {align-items: center;
    }
    
  6. align-content

    • 控制多行(有换行时)在交叉轴上的对齐方式。
    • flex-start:行靠交叉轴的起始位置对齐。
    • flex-end:行靠交叉轴的末尾位置对齐。
    • center:行在交叉轴上居中对齐。
    • space-between:行间隔相等,第一个和最后一个行与容器边缘对齐。
    • space-around:行间隔相等,行与容器之间也有间隔。
    • stretch(默认):行拉伸以填充容器。
    .container {align-content: space-between;
    }
    

二、Flex 项目属性
  1. order

    • 控制项目的排列顺序,数字越小,排列越靠前,默认为 0
    .item {order: 1;
    }
    
  2. flex-grow

    • 定义项目如何在主轴方向上扩展,以填充容器中剩余的空间。默认为 0,表示不扩展。
    • 如果所有项目的 flex-grow 值相同,空间会均等分配。
    .item {flex-grow: 1;
    }
    
  3. flex-shrink

    • 定义项目如何在容器空间不足时缩小。默认为 1,表示项目会缩小。
    • 如果设置为 0,则项目不会缩小。
    .item {flex-shrink: 0;
    }
    
  4. flex-basis

    • 定义项目在分配剩余空间之前的初始大小。默认值为 auto,即根据项目的内容或宽度来决定。
    • 可以设置为具体的像素值、百分比等。
    .item {flex-basis: 200px;
    }
    
  5. flex

    • flexflex-growflex-shrinkflex-basis 的简写。
    • 常见的值:
      • flex: 1 等价于 flex-grow: 1; flex-shrink: 1; flex-basis: 0%,让项目在可用空间中均等分配。
      • 5:3:2分->flex值分别设为5、3、2
      • flex: auto 等价于 flex-grow: 1; flex-shrink: 1; flex-basis: auto
      • flex: none 等价于 flex-grow: 0; flex-shrink: 0; flex-basis: auto,不允许扩展或收缩,保持初始大小。
    .item {flex: 1;
    }
    
  6. align-self

    • 控制单个项目在交叉轴上的对齐方式,覆盖 align-items 设置。
    • 可选值:autoflex-startflex-endcenterbaselinestretch
    .item {align-self: center;
    }
    

Flexbox 为响应式设计提供了非常强大的支持,尤其在复杂布局或动态调整时,能够通过这些属性轻松控制元素的排列、对齐和间距。

媒体查询

媒体查询详解

媒体查询(Media Queries)是 CSS3 提供的一种功能,用于根据设备的特性(如屏幕大小、分辨率、方向等)应用不同的样式,从而实现响应式设计。

媒体查询主要用于适配不同的设备,如桌面、平板、手机等。


1. 基本语法

媒体查询的基本语法如下:

@media media-type and (media-feature: value) {/* CSS规则 */
}
  • media-type:媒体类型,例如 screenprint
  • media-feature:媒体特性,例如屏幕宽度、分辨率。
  • value:具体值,用于定义某个媒体特性的范围或条件。

2. 媒体类型

媒体查询支持以下媒体类型:

媒体类型描述
all默认值,适用于所有设备。
screen针对屏幕设备,例如电脑、平板、手机等。
print针对打印设备。
speech针对屏幕阅读器等语音设备。

示例:

@media screen {body {background-color: lightblue;}
}

3. 常用媒体特性

媒体特性用于检测设备的具体属性,以下是常用媒体特性及其说明:

特性描述
width视口(viewport)的宽度。
height视口的高度。
min-width视口的最小宽度。
max-width视口的最大宽度。
min-height视口的最小高度。
max-height视口的最大高度。
aspect-ratio视口的宽高比,例如 16/9
orientation设备方向:portrait(竖屏)或 landscape(横屏)。
resolution屏幕分辨率,例如 300dpi2dppx
prefers-color-scheme用户的首选颜色模式:lightdark

4. 媒体查询的逻辑运算符

媒体查询支持以下逻辑运算符,允许结合多个条件:

4.1 and
  • 用于同时满足多个条件。
@media screen and (min-width: 768px) and (orientation: landscape) {body {background-color: lightgreen;}
}
4.2 not
  • 用于排除某些条件。
@media not screen and (max-width: 768px) {body {background-color: pink;}
}
4.3 ,(逗号,等价于“or”)
  • 用于满足任一条件即可生效。
@media (max-width: 768px), (orientation: landscape) {body {font-size: 14px;}
}

5. 媒体查询的使用方式

5.1 在 CSS 文件中

直接在 CSS 文件中使用 @media

@media (max-width: 768px) {body {background-color: lightyellow;}
}
5.2 在 <style> 标签中

在 HTML 文件的 <style> 标签中使用:

<style>@media (max-width: 768px) {body {background-color: lightyellow;}}
</style>
5.3 在 HTML 的 <link> 标签中

通过 media 属性为外部 CSS 文件指定条件:

<link rel="stylesheet" href="style.css" media="screen and (max-width: 768px)">

6. 响应式设计中的常用断点

响应式设计中,为不同设备设置“断点”是常见做法。以下是常见设备的屏幕宽度断点:

设备类型常用断点范围
超小屏幕(手机)max-width: 576px
小屏幕(平板)min-width: 577pxmax-width: 768px
中等屏幕(桌面)min-width: 769pxmax-width: 992px
大屏幕(大桌面)min-width: 993pxmax-width: 1200px
超大屏幕min-width: 1201px

示例:

/* 手机样式 */
@media (max-width: 576px) {body {font-size: 14px;}
}/* 平板样式 */
@media (min-width: 577px) and (max-width: 768px) {body {font-size: 16px;}
}/* 桌面样式 */
@media (min-width: 769px) {body {font-size: 18px;}
}

7. 媒体查询的最佳实践

  1. 优先考虑移动优先设计(Mobile First)

    • 先为小屏幕(如手机)编写样式,再为更大的屏幕覆盖样式。
    • 使用 min-width 编写媒体查询:
    body {font-size: 14px; /* 默认样式 */
    }@media (min-width: 768px) {body {font-size: 16px; /* 平板样式 */}
    }@media (min-width: 992px) {body {font-size: 18px; /* 桌面样式 */}
    }
    
  2. 保持断点清晰

    • 确保不同断点之间没有冲突,避免重复规则。
  3. 避免过多的媒体查询

    • 尽量保持规则简单,并利用 flexboxgrid 等现代布局方法减少依赖媒体查询的需求。
  4. 测试多设备

    • 使用浏览器的开发者工具测试不同的屏幕尺寸和方向,确保样式正常工作。

8. 示例:完整的响应式布局

/* 默认样式(移动优先) */
body {font-size: 14px;background-color: lightblue;
}/* 平板设备 */
@media (min-width: 768px) {body {font-size: 16px;background-color: lightgreen;}
}/* 桌面设备 */
@media (min-width: 992px) {body {font-size: 18px;background-color: lightcoral;}
}

9. 新特性:容器查询(Container Queries)

容器查询是媒体查询的补充(CSS Container Queries),它允许根据容器的大小而不是视口大小来应用样式。虽然媒体查询以设备为基础,但容器查询更关注组件的自适应。

目前,容器查询还在发展中,部分现代浏览器已经支持。

实现

Pinia全局状态管理

管理当前设备类型(deviceType)、导航条是否需折叠(isCollapse)
Pinia

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useDeviceStore=defineStore('device',{state:()=>({deviceType:"desktop" as deviceType, //初始默认值isCollapse:false,// deviceType:DeviceTypeEnum.Desktop,}),actions:{toggleDevice(type:deviceType){this.deviceType=type;},toggleCollapse(flag: boolean){this.isCollapse=flag;}}
})

监测设备变化

监测视口变化,改变全局状态(deviceType、isCollapse)

Vue2中借助mixin
import store from '@/store'const { body } = document
const WIDTH = 992 // refer to Bootstrap's responsive designexport default {watch: {$route(route) {if (this.device === 'mobile' && this.sidebar.opened) {store.dispatch('app/closeSideBar', { withoutAnimation: false })}}},beforeMount() {window.addEventListener('resize', this.$_resizeHandler)},beforeDestroy() {window.removeEventListener('resize', this.$_resizeHandler)},mounted() {const isMobile = this.$_isMobile()if (isMobile) {store.dispatch('app/toggleDevice', 'mobile')store.dispatch('app/closeSideBar', { withoutAnimation: true })}},methods: {// use $_ for mixins properties// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential$_isMobile() {const rect = body.getBoundingClientRect()return rect.width - 1 < WIDTH},$_resizeHandler() {if (!document.hidden) {const isMobile = this.$_isMobile()store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')if (isMobile) {store.dispatch('app/closeSideBar', { withoutAnimation: true })}}}}
}
  mixins: [ResizeMixin],
Vue3中借助组合式API

import { onMounted, onBeforeUnmount, watch } from 'vue';
import { useDeviceStore } from '@/stores/layout';  // 引入 Pinia storeconst WIDTH = 768;
// 参考 Bootstrap 的响应式设计
//常见断点:576mobile\768iPad\992MidDesktop\1200LargeDeasktop\export function useDevice() {const deviceStore = useDeviceStore();  // 使用 Pinia storeconst body = document.body;// 判断当前屏幕是否为移动端const isMobile = () => {const rect = body.getBoundingClientRect();return rect.width - 1 < WIDTH;};// 响应式处理函数const resizeHandler = () => {if (!document.hidden) {const isMobileDevice = isMobile();deviceStore.toggleDevice(isMobileDevice ? 'mobile' : 'desktop');}};// 在组件挂载时进行初始化onMounted(() => {if (isMobile()) {deviceStore.toggleDevice('mobile');deviceStore.toggleCollapse(true);}window.addEventListener('resize', resizeHandler); // 监听窗口大小变化});// 在组件销毁时移除事件监听onBeforeUnmount(() => {window.removeEventListener('resize', resizeHandler);});// 监听设备类型变化,移动设备时关闭侧边栏watch(() => deviceStore.deviceType, (newDevice) => {if (newDevice === 'mobile' && !deviceStore.isCollapse) {deviceStore.toggleCollapse(true);}else {deviceStore.toggleCollapse(false);}});return {isMobile,  // 返回判断当前是否为移动设备的方法};
}
<script setup lang="ts">
import {useDevice} from '@/layout/mixin/ResizeHandler'
useDevice();
</script>

媒体查询

不同设备下布局样式调整,调整导航条布局
设备为中小设备时,导航条就折叠且放在最右侧

<div id="app"><!-- 顶部导航栏 --><el-header class="header"><div class="logo">LOGO</div><div class="nav"><Nav></Nav></div><div class="info"><el-row :gutter="20"><el-col :span="8"><theme></theme></el-col><el-col :span="8"><el-icon :size="40"><Git></Git></el-icon></el-col><el-col :span="8"><Translation></Translation></el-col></el-row></div></el-header><!-- 内容区域 --><el-main class="main"><div class="content"><!-- 动态显示内容 --><RouterView></RouterView></div></el-main></div>
///* 响应式布局 */
@media (min-width: 769px) {.logo {font-size: 24px;font-weight: bold;flex:5;}.nav{background-color: transparent;border-bottom: none;flex: 3.5;}.info{flex:1.5;margin-left: 20px;//background-color: white;}
}
@media (max-width: 768px) {.logo {font-size: 24px;font-weight: bold;flex:5;order:0//排序顺序,order属性}.nav{background-color: transparent;border-bottom: none;flex:1;//设备为中小设备时,导航条就折叠且放在最右侧!order:2}.info{flex:4;margin-left: 20px;order:1}}

导航条状态绑定

导航条绑定全局状态(isCollapse)

<template><el-menuclass="menu"mode="horizontal":popper-offset="16"style="max-width: 600px":collapse="deviceStore.isCollapse"></el-menu><script setup lang="ts">
import {useDeviceStore} from '@/stores/layout'
import { watch } from 'vue'
//根据当前窗口大小,判断是否折叠导航条
const deviceStore=useDeviceStore();
watch(()=>deviceStore.isCollapse,(newValue)=>{console.log(newValue)
})
</script>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词