// 布局专用LESS文件 // 包含常用的布局混合宏和样式 // ------------------------------ // 容器布局 // ------------------------------ // 全屏容器 .full-screen { width: 100%; height: 100vh; } // 固定宽度容器 .container-fixed(@width: 1200px) { width: @width; margin: 0 auto; padding: 0 20px; } // 响应式容器 .container-responsive { width: 100%; margin: 0 auto; padding: 0 20px; max-width: 1200px; } // ------------------------------ // Flex布局混合宏 // ------------------------------ // 基础Flex布局 .flex(@direction: row; @wrap: nowrap; @justify: flex-start; @align: stretch) { display: flex; flex-direction: @direction; flex-wrap: @wrap; justify-content: @justify; align-items: @align; } // 居中布局 .flex-center { .flex(row, nowrap, center, center); } // 两端对齐 .flex-between { .flex(row, nowrap, space-between, center); } // 顶部对齐 .flex-start { .flex(row, nowrap, flex-start, flex-start); } // 底部对齐 .flex-end { .flex(row, nowrap, flex-end, flex-end); } // 垂直居中 .flex-middle { .flex(row, nowrap, flex-start, center); } // 垂直布局 .flex-column { .flex(column, nowrap, flex-start, stretch); } // 垂直居中布局 .flex-column-center { .flex(column, nowrap, center, center); } // 垂直两端对齐 .flex-column-between { .flex(column, nowrap, space-between, stretch); } // ------------------------------ // 网格布局 // ------------------------------ // 基础网格容器 .grid(@columns: 12; @gap: 20px) { display: grid; grid-template-columns: repeat(@columns, 1fr); grid-gap: @gap; gap: @gap; } // 响应式网格 .grid-responsive(@columns: 12; @gap: 20px) { .grid(@columns, @gap); @media (max-width: 768px) { grid-template-columns: repeat(6, 1fr); } @media (max-width: 480px) { grid-template-columns: repeat(3, 1fr); } } // 网格列宽 .grid-col(@span: 1) { grid-column: span @span; } // 网格行高 .grid-row(@span: 1) { grid-row: span @span; } // ------------------------------ // 定位布局 // ------------------------------ // 绝对定位 .position-absolute(@top: auto; @right: auto; @bottom: auto; @left: auto) { position: absolute; top: @top; right: @right; bottom: @bottom; left: @left; } // 固定定位 .position-fixed(@top: auto; @right: auto; @bottom: auto; @left: auto) { position: fixed; top: @top; right: @right; bottom: @bottom; left: @left; } // 粘性定位 .position-sticky(@top: 0; @z-index: 10) { position: sticky; top: @top; z-index: @z-index; } // 居中定位(基于父容器) .position-center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } // 水平居中定位 .position-center-x { position: absolute; left: 50%; transform: translateX(-50%); } // 垂直居中定位 .position-center-y { position: absolute; top: 50%; transform: translateY(-50%); } // ------------------------------ // 间距布局 // ------------------------------ // 外边距 .margin(@top: 0; @right: @top; @bottom: @top; @left: @right) { margin: @top @right @bottom @left; } // 内边距 .padding(@top: 0; @right: @top; @bottom: @top; @left: @right) { padding: @top @right @bottom @left; } // 间距工具类(基于4px网格系统) .spacing-utilities(@prefix: m; @property: margin) { .loop(@i) when (@i <= 12) { .@{prefix}-@{i} { @{property}: @i * 4px; } .@{prefix}t-@{i} { @{property}-top: @i * 4px; } .@{prefix}r-@{i} { @{property}-right: @i * 4px; } .@{prefix}b-@{i} { @{property}-bottom: @i * 4px; } .@{prefix}l-@{i} { @{property}-left: @i * 4px; } .loop(@i + 1); } .loop(0); } // 生成外边距工具类 .spacing-utilities(m, margin); // 生成内边距工具类 .spacing-utilities(p, padding); // ------------------------------ // 卡片布局 // ------------------------------ // 基础卡片 .card(@radius: 8px; @shadow: 0 2px 8px rgba(0, 0, 0, 0.1); @bg: #fff) { background-color: @bg; border-radius: @radius; box-shadow: @shadow; overflow: hidden; } // 带边框的卡片 .card-bordered(@radius: 8px; @border-color: #e5e5e5; @bg: #fff) { .card(@radius, none, @bg); border: 1px solid @border-color; } // 卡片头部 .card-header { padding: 16px 20px; border-bottom: 1px solid #e5e5e5; } // 卡片主体 .card-body { padding: 20px; } // 卡片底部 .card-footer { padding: 16px 20px; border-top: 1px solid #e5e5e5; background-color: #fafafa; } // ------------------------------ // 导航栏布局 // ------------------------------ // 基础导航栏 .navbar(@height: 60px; @bg-color: #fff; @text-color: #333) { height: @height; background-color: @bg-color; color: @text-color; display: flex; align-items: center; padding: 0 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); } // 顶部导航栏 .navbar-top { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; .navbar(); } // 底部导航栏 .navbar-bottom { position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; .navbar(); border-top: 1px solid #e5e5e5; } // ------------------------------ // 页面布局 // ------------------------------ // 基础页面布局 .page-layout { min-height: 100vh; display: flex; flex-direction: column; } // 带头部和底部的页面布局 .page-with-header-footer { .page-layout(); .page-header { flex-shrink: 0; } .page-content { flex: 1; padding: 20px; overflow-y: auto; } .page-footer { flex-shrink: 0; } } // ------------------------------ // 响应式布局 // ------------------------------ // 断点定义 @breakpoint-sm: 480px; @breakpoint-md: 768px; @breakpoint-lg: 1024px; @breakpoint-xl: 1200px; // 媒体查询混合宏 .media-sm(@rules) { @media (max-width: @breakpoint-sm) { @rules(); } } .media-md(@rules) { @media (max-width: @breakpoint-md) { @rules(); } } .media-lg(@rules) { @media (max-width: @breakpoint-lg) { @rules(); } } .media-xl(@rules) { @media (max-width: @breakpoint-xl) { @rules(); } } // 响应式显示/隐藏 .hidden-sm { .media-sm({ display: none; }); } .visible-sm { display: none; .media-sm({ display: block; }); } .hidden-md { .media-md({ display: none; }); } .visible-md { display: none; .media-md({ display: block; }); } // ------------------------------ // 其他布局工具 // ------------------------------ // 清除浮动 .clearfix { &::after { content: ''; display: table; clear: both; } } // 相对定位 .relative { position: relative; } // 绝对定位 .absolute { position: absolute; } // 固定定位 .fixed { position: fixed; } // 粘性定位 .sticky { position: sticky; } // 隐藏溢出 .overflow-hidden { overflow: hidden; } // 自动溢出 .overflow-auto { overflow: auto; } // 水平滚动 .overflow-x-auto { overflow-x: auto; overflow-y: hidden; } // 垂直滚动 .overflow-y-auto { overflow-y: auto; overflow-x: hidden; } // 全屏高度 .full-height { height: 100%; min-height: 100vh; } // 全屏宽度 .full-width { width: 100%; max-width: 100%; }