// ======================================================== // 1. 变量与断点定义 (集中管理) // ======================================================== $breakpoints: ( 'mobile': 768px, 'tablet': 1024px, 'desktop': 1920px, '2k': 2560px, '4k-40': 3800px, '4k': 3840px ); // 字号常量 $font-size-small: 14px; // 手机/平板基准 $font-size-standard: 16px; // 桌面基准 (1024px - 3840px) $font-size-4k-base: 20px; // 4K 触发点字号 // 容器配置 $container-paddings: 1rem; /// 去除单位函数 @function strip-unit($number) { @if type-of($number) == 'number' and not unitless($number) { @return $number / ($number * 0 + 1); } @return $number; } /// 计算基于屏幕宽度的线性 VW 比例 /// @param $size - 目标字号 (如 24px) /// @param $breakpoint - 触发断点 (如 3840) @function get-linear-vw($size, $breakpoint) { $raw-size: strip-unit($size); $raw-breakpoint: strip-unit($breakpoint); @return ($raw-size / $raw-breakpoint) * 100vw; } // ======================================================== // 2. 媒体查询 Mixin // ======================================================== @mixin respond-to($breakpoint) { // 如果是预定义的 key (如 'mobile') @if map-has-key($breakpoints, $breakpoint) { @media (min-width: map-get($breakpoints, $breakpoint)) { @content; } } // 如果是传入的具体数值 (如 3840px) @else { @media (min-width: $breakpoint) { @content; } } } // ======================================================== // 3. 核心响应式逻辑 // ======================================================== :root { // --- [阶段 A] 默认状态 (手机/小屏幕) --- font-size: $font-size-small; // --- [阶段 B] 1024px 以上到 4K 之前: 保持标准 16px --- @include respond-to('tablet') { font-size: $font-size-standard; } // --- [阶段 C] 大于 4K: 开启线性增长 --- @include respond-to('4k') { // 锁定最小字号为 20px,确保在任何情况下都不会比基准值小 font-size: clamp(#{$font-size-4k-base}, get-linear-vw($font-size-4k-base, 3840), 100vw); } } /* --- 全局布局容器适配 --- */ // 其中 4k-40 为准 4K (即 3840px - 40px), 以适配 PC 端部分浏览器最大化时边框占位从而影响到 4K 宽度判定 .container { width: 100%; margin: 0 auto; padding: 0 $container-paddings; box-sizing: border-box; @include respond-to('mobile') { max-width: 720px; } @include respond-to('tablet') { max-width: 960px; } @include respond-to('desktop') { max-width: 1800px; } @include respond-to('2k') { max-width: 2560px; } @include respond-to('4k-40') { max-width: 3800px; } // 当容器等于 4K 时,随之线性扩大 @include respond-to('4k') { // 保持容器宽度占比: (3600 / 3840) * 100vw = 93.75vw max-width: (3600 / 3840) * 100vw; } } // ======================================================== // 4. 工具类与组件样式 // ======================================================== // 这里的 1rem 会随着 :root 的 font-size 变化而自动缩放 /* --- 工具与组件样式 --- */ .nav-link { &:visited { color: inherit; } &.active { font-weight: bold; color: var(--bs-link-hover-color, rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1))) !important; border-bottom: 2px solid var(--bs-link-hover-color, rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1))); } } .p-r-t { position: relative; top: -1px; } .mg-0 { margin: 0 auto; } // 去除 a 标签默认下划线 a { text-decoration: none; color: var(--bs-link-hover-color, rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1))); // 访问过的链接变更颜色,提供视觉反馈 &:visited { color: var(--bs-purple, rgba(var(--bs-primary), var(--bs-link-opacity, 0.8))); } } // 定义宽与高的工具类,使用 rem 单位以适配响应式字体大小 $widthOrheight-map: ( '1r': 1rem, '1_5r': 1.5rem, '2r': 2rem, '2_5r': 2.5rem, '3r': 3rem, '3_5r': 3.5rem, '4r': 4rem, '4_5r': 4.5rem, '5r': 5rem, '5_5r': 5.5rem ); @each $key, $value in $widthOrheight-map { .w-#{$key} { width: $value; } .h-#{$key} { height: $value; } }