Merge branch 'main' of http://10.1.1.5:8418/acdiu/AcdiuTools
This commit is contained in:
28
Constants/UIConstants.cs
Normal file
28
Constants/UIConstants.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
namespace AcdiuTools.Constants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 全局 UI 常量定义
|
||||||
|
/// </summary>
|
||||||
|
public static class UIConstants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 资源路径常量
|
||||||
|
/// </summary>
|
||||||
|
public static class Paths
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 默认 Bootstrap Icons SVG Sprite 文件路径
|
||||||
|
/// </summary>
|
||||||
|
public const string DefaultIconSprite = "/lib/bootstrap-icons-1.13.1/bootstrap-icons.svg";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BS SVG 图标默认需要添加的 CSS 类名
|
||||||
|
/// </summary>
|
||||||
|
public static class Classes
|
||||||
|
{
|
||||||
|
public const string DefaultWidth = "w-1r";
|
||||||
|
public const string DefaultHeight = "h-1r";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,127 +1,167 @@
|
|||||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AcdiuTools.Constants;
|
||||||
|
|
||||||
namespace AcdiuTools.TagHelpers
|
namespace AcdiuTools.TagHelpers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see langword="Bootstrap Icons"></see> SVG Sprite 封装标签
|
/// <see langword="Bootstrap Icons"/> SVG Sprite 封装标签。
|
||||||
/// 用法: <bsicon i="heart-fill" w="16" h="16" f="red" />
|
/// <para>支持自动缩放逻辑:若未指定宽高,则默认添加 w-1r/h-1r 类名以适配响应式根字号。</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// 用法: <bsicon i="heart-fill" w="20" f="red" />
|
||||||
|
/// 或: <bsicon icon="alarm" width="1rem" cn="my-style" />
|
||||||
|
/// </example>
|
||||||
[HtmlTargetElement("bsicon")]
|
[HtmlTargetElement("bsicon")]
|
||||||
public class BsIconTagHelper : TagHelper
|
public class BsIconTagHelper : TagHelper
|
||||||
{
|
{
|
||||||
// 路径指向你存放总 SVG 的位置
|
// 内部逻辑变量
|
||||||
/// <summary>
|
private string _iconName = string.Empty;
|
||||||
/// 表示用于引用图标符号的 <see langword="Bootstrap Icons"></see> SVG矢量图库文件的相对路径
|
private string _width = string.Empty;
|
||||||
/// </summary>
|
private string _height = string.Empty;
|
||||||
/// <remarks>此路径应指向包含所有 <see langword="Bootstrap"></see> 图标定义的SVG文件<br/>
|
private string _fill = "currentColor";
|
||||||
/// 如果图标库被移动或升级,则需要更新该值</remarks>
|
|
||||||
const string spritePath = "/lib/bootstrap-icons-1.13.1/bootstrap-icons.svg";
|
#region 属性定义 (支持别名)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图标名称 (必填)
|
/// 图标名称 (必填)。对应 SVG 中的 ID。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HtmlAttributeName("i")]
|
[HtmlAttributeName("i")]
|
||||||
public required string IconName { get; set; }
|
public string I { get => _iconName; set => _iconName = value; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 宽度 (默认为空,若为空时设置了高度,则使用高度的值,否则为元素 ClassName 添加 w-1r 以使其默认宽度为 1rem)
|
/// 图标名称 (别名)。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("icon")]
|
||||||
|
public string Icon { get => _iconName; set => _iconName = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 宽度。支持数字或 CSS 单位(如 16, 1rem)。
|
||||||
|
/// <remarks>若为空则尝试使用高度值,若均为空则添加默认响应式类名。</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HtmlAttributeName("w")]
|
[HtmlAttributeName("w")]
|
||||||
public string Width { get; set; } = string.Empty;
|
public string W { get => _width; set => _width = value; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 高度 (默认为空,若为空时设置了宽度,则使用宽度的值,否则为元素 ClassName 添加 h-1r 以使其默认高度为 1rem)
|
/// 宽度 (别名)。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("width")]
|
||||||
|
public string Width { get => _width; set => _width = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 高度。支持数字或 CSS 单位。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HtmlAttributeName("h")]
|
[HtmlAttributeName("h")]
|
||||||
public string Height { get; set; } = string.Empty;
|
public string H { get => _height; set => _height = value; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 填充颜色 (默认 currentColor 即当前元素颜色)
|
/// 高度 (别名)。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("height")]
|
||||||
|
public string Height { get => _height; set => _height = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 填充颜色。默认为 <c>currentColor</c>。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HtmlAttributeName("f")]
|
[HtmlAttributeName("f")]
|
||||||
public string Fill { get; set; } = "currentColor";
|
public string F { get => _fill; set => _fill = value; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义 class 名称,允许用户添加额外的样式类 (默认空)
|
/// 填充颜色 (别名)。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("fill")]
|
||||||
|
public string Fill { get => _fill; set => _fill = value; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义 CSS 类名。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("c")]
|
||||||
|
public string C { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义 CSS 类名 (别名)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HtmlAttributeName("cn")]
|
[HtmlAttributeName("cn")]
|
||||||
|
public string CN { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义 CSS 类名 (别名)。
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("class")]
|
||||||
public string ClassName { get; set; } = string.Empty;
|
public string ClassName { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据指定的图标名称和属性,处理标签助手以渲染SVG矢量图标
|
/// 自定义 SVG Sprite 路径。
|
||||||
|
/// <remarks>不填则使用系统默认常量路径。</remarks>
|
||||||
|
/// </summary>
|
||||||
|
[HtmlAttributeName("path")]
|
||||||
|
public string CustomPath { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理标签渲染逻辑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>若未指定图标名称或为空,则输出被抑制且不生成SVG<br/>
|
|
||||||
/// 渲染后,该方法会将原始标签替换为<svg>元素并设置标准的SVG属性<br/>
|
|
||||||
/// 包括类名、宽度、高度、填充颜色和图标ID名称。该SVG引用了 <see langword="Bootstrap Icons"></see> 中的图标<br/>
|
|
||||||
/// 使用<use>元素引用的矢量图形</remarks>
|
|
||||||
/// <param name="context">用于标签辅助程序执行的上下文,包含当前HTML标签及其属性的相关信息</param>
|
|
||||||
/// <param name="output">标签辅助器的输出,用于修改渲染的HTML元素及其内容</param>
|
|
||||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(IconName))
|
if (string.IsNullOrWhiteSpace(_iconName))
|
||||||
{
|
{
|
||||||
output.SuppressOutput(); // 如果没写图标名,则不渲染
|
output.SuppressOutput();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 将外层标签替换为 <svg>
|
// 1. 设置基础标签属性
|
||||||
output.TagName = "svg";
|
output.TagName = "svg";
|
||||||
output.TagMode = TagMode.StartTagAndEndTag;
|
output.TagMode = TagMode.StartTagAndEndTag;
|
||||||
|
output.Attributes.SetAttribute("fill", _fill);
|
||||||
|
output.Attributes.SetAttribute("viewBox", "0 0 16 16");
|
||||||
|
|
||||||
// 2. 设置 SVG 基础属性
|
// 2. 处理宽高与类名逻辑
|
||||||
// 如果设置了 w 或 h,则优先使用它们,否则使用 wh 的值
|
bool hasW = !string.IsNullOrWhiteSpace(_width);
|
||||||
// 设定机制:
|
bool hasH = !string.IsNullOrWhiteSpace(_height);
|
||||||
// 如果 w 和 h 中任意一个不为空,则使用不为空的 w 或 h 的值同时设置宽高;
|
|
||||||
// 如果 w 和 h 都不为空,则分别使用它们设置宽高;
|
if (hasW || hasH)
|
||||||
// 如果 w 和 h 都为空,则为其添加默认的 w-1r 和 h-1r 类以设置默认宽高为 1rem
|
|
||||||
if (!string.IsNullOrWhiteSpace(Width) || !string.IsNullOrWhiteSpace(Height))
|
|
||||||
{
|
{
|
||||||
// 如果用户设置了宽或高,则不添加默认的 w-1r 和 h-1r 类
|
// 只要设置了任意一个,就手动赋值 width/height 属性
|
||||||
output.Attributes.SetAttribute("width", !string.IsNullOrWhiteSpace(Width) ? Width : Height);
|
output.Attributes.SetAttribute("width", hasW ? _width : _height);
|
||||||
output.Attributes.SetAttribute("height", !string.IsNullOrWhiteSpace(Height) ? Height : Width);
|
output.Attributes.SetAttribute("height", hasH ? _height : _width);
|
||||||
|
|
||||||
// 继续添加用户自定义的 ClassName (如果有的话)
|
// 设置类名(不添加默认响应式类)
|
||||||
output.Attributes.SetAttribute("class", MergeClassNames(string.IsNullOrWhiteSpace(ClassName) ? "" : $"{ClassName}"));
|
output.Attributes.SetAttribute("class", ClassName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 如果没有设置宽高,则添加默认的 w-1r 和 h-1r 类并与用户自定义的 ClassName 合并
|
// 均未设置,则应用响应式默认类名并去重
|
||||||
// 如果提供了 ClassName,则判断是否为空,如果不为空则将其与默认的 w-1r 和 h-1r 类合并
|
output.Attributes.SetAttribute("class", BuildResponsiveClasses(ClassName));
|
||||||
// 合并时使用 HashSet 来去重,确保不会重复添加相同的类名
|
|
||||||
output.Attributes.SetAttribute("class", MergeClassNames(ClassName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output.Attributes.SetAttribute("fill", Fill);
|
// 3. 构建内部内容
|
||||||
output.Attributes.SetAttribute("viewBox", "0 0 16 16"); // 保证矢量对齐
|
string finalPath = string.IsNullOrWhiteSpace(CustomPath)
|
||||||
//output.Attributes.SetAttribute("xmlns", "http://www.w3.org/2000/svg");
|
? UIConstants.Paths.DefaultIconSprite
|
||||||
|
: CustomPath;
|
||||||
|
|
||||||
// 3. 构造内部的 <use> 节点
|
output.Content.SetHtmlContent($@"<use xlink:href=""{finalPath}#{_iconName}""></use>");
|
||||||
var content = $@"<use xlink:href=""{spritePath}#{IconName}""></use>";
|
|
||||||
|
|
||||||
output.Content.SetHtmlContent(content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 合并类名的方法,确保默认的 w-1r 和 h-1r 类与用户提供的 ClassName 合并且去重
|
/// 构建响应式类名字符串,确保默认类名存在且去重
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userClassName">用户提供的类名</param>
|
private string BuildResponsiveClasses(string userClassName)
|
||||||
/// <returns>合并且去重后的类名字符串</returns>
|
|
||||||
public static string MergeClassNames(string userClassName)
|
|
||||||
{
|
{
|
||||||
// 定义默认的类列表
|
var classes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
var defaultClasses = new HashSet<string> { "w-1r", "h-1r" };
|
{
|
||||||
// 如果用户提供了 ClassName,则将其拆分成单个类并添加到集合中
|
UIConstants.Classes.DefaultWidth,
|
||||||
|
UIConstants.Classes.DefaultHeight
|
||||||
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(userClassName))
|
if (!string.IsNullOrWhiteSpace(userClassName))
|
||||||
{
|
{
|
||||||
var userClasses = userClassName.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
var userParts = userClassName.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (var cls in userClasses)
|
foreach (var item in userParts) classes.Add(item);
|
||||||
{
|
|
||||||
defaultClasses.Add(cls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 将集合中的类名合并成一个字符串返回
|
|
||||||
return string.Join(" ", defaultClasses);
|
return string.Join(" ", classes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="~/AcdiuTools.styles.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/AcdiuTools.styles.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="~/ac/ac.min.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/ac/ac.min.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="~/ac/icon/all.css" asp-append-version="true" />
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|||||||
@@ -38,6 +38,16 @@
|
|||||||
max-width: 1800px;
|
max-width: 1800px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media (min-width: 2560px) {
|
||||||
|
.container {
|
||||||
|
max-width: 2560px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 3800px) {
|
||||||
|
.container {
|
||||||
|
max-width: 3800px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media (min-width: 3840px) {
|
@media (min-width: 3840px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 93.75vw;
|
max-width: 93.75vw;
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
:root {
|
|
||||||
/* --- 基础断点定义 (供参考) --- */
|
|
||||||
/* 手机: < 768px */
|
|
||||||
/* 平板: 768px - 1024px */
|
|
||||||
/* 桌面: 1024px - 1920px */
|
|
||||||
/* 4K屏: 3840px */
|
|
||||||
/* --- 核心字号缩放逻辑 --- */
|
|
||||||
/* 逻辑: 在移动端最小为 14px,在 1024px 以上开始线性增长,到 4K 达到 24px */
|
|
||||||
/* 公式: clamp(最小值, 首选值, 最大值) */
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
:root {
|
|
||||||
/* 1.2vw + 10px 是一个经过计算的动态值,确保 1024-3840 之间平滑过渡 */
|
|
||||||
font-size: clamp(16px, 0.35vw + 12.4px, 24px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 3840px) {
|
|
||||||
:root {
|
|
||||||
/* 针对 4K 以上屏幕,如果想继续缩放可保持 clamp,想锁定则固定 24px */
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- 全局布局容器 --- */
|
|
||||||
.container {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 1rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
/* 这里的 1rem 会随着上面定义的 font-size 自动缩放 */
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.container {
|
|
||||||
max-width: 720px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.container {
|
|
||||||
max-width: 960px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1920px) {
|
|
||||||
.container {
|
|
||||||
max-width: 1800px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 3840px) {
|
|
||||||
.container {
|
|
||||||
max-width: 3600px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 为当前激活的 nav-link,增加加粗效果 */
|
|
||||||
.nav-link.active {
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--bs-primary) !important;
|
|
||||||
border-bottom: 2px solid var(--bs-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-r-t {
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-1r {
|
|
||||||
width: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-1r {
|
|
||||||
height: 1rem;
|
|
||||||
}
|
|
||||||
2
wwwroot/ac/ac.min.css
vendored
2
wwwroot/ac/ac.min.css
vendored
@@ -1 +1 @@
|
|||||||
@charset "UTF-8";:root{font-size:14px;}@media(min-width:1024px){:root{font-size:16px;}}@media(min-width:3840px){:root{font-size:.625vw;}}.container{width:100%;margin:0 auto;padding:0 1rem;box-sizing:border-box;}@media(min-width:768px){.container{max-width:720px;}}@media(min-width:1024px){.container{max-width:960px;}}@media(min-width:1920px){.container{max-width:1800px;}}@media(min-width:3840px){.container{max-width:93.75vw;}}.w-1r{width:1rem;}.h-1r{height:1rem;}.nav-link.active{font-weight:bold;color:var(--bs-primary)!important;border-bottom:2px solid var(--bs-primary);}.p-r-t{position:relative;top:-1px;}mg-0{margin:0 auto;}
|
@charset "UTF-8";:root{font-size:14px;}@media(min-width:1024px){:root{font-size:16px;}}@media(min-width:3840px){:root{font-size:.625vw;}}.container{width:100%;margin:0 auto;padding:0 1rem;box-sizing:border-box;}@media(min-width:768px){.container{max-width:720px;}}@media(min-width:1024px){.container{max-width:960px;}}@media(min-width:1920px){.container{max-width:1800px;}}@media(min-width:2560px){.container{max-width:2560px;}}@media(min-width:3800px){.container{max-width:3800px;}}@media(min-width:3840px){.container{max-width:93.75vw;}}.w-1r{width:1rem;}.h-1r{height:1rem;}.nav-link.active{font-weight:bold;color:var(--bs-primary)!important;border-bottom:2px solid var(--bs-primary);}.p-r-t{position:relative;top:-1px;}mg-0{margin:0 auto;}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// ========================================================
|
// ========================================================
|
||||||
// 1. 变量与断点定义 (集中管理)
|
// 1. 变量与断点定义 (集中管理)
|
||||||
// ========================================================
|
// ========================================================
|
||||||
$breakpoints: ( 'mobile': 768px, 'tablet': 1024px, 'desktop': 1920px, '4k': 3840px );
|
$breakpoints: ( 'mobile': 768px, 'tablet': 1024px, 'desktop': 1920px, '2k': 2560px, '4k-40': 3800px, '4k': 3840px );
|
||||||
|
|
||||||
// 字号常量
|
// 字号常量
|
||||||
$font-size-small: 14px; // 手机/平板基准
|
$font-size-small: 14px; // 手机/平板基准
|
||||||
@@ -49,6 +49,7 @@ $container-paddings: 1rem;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* --- 全局布局容器适配 --- */
|
/* --- 全局布局容器适配 --- */
|
||||||
|
// 其中 4k-40 为准 4K, 以适配 PC 端部分浏览器最大化时边框占位从而影响到 4K 宽度判定
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -66,7 +67,15 @@ $container-paddings: 1rem;
|
|||||||
@include respond-to('desktop') {
|
@include respond-to('desktop') {
|
||||||
max-width: 1800px;
|
max-width: 1800px;
|
||||||
}
|
}
|
||||||
// 4K 以上容器随之线性扩大
|
|
||||||
|
@include respond-to('2k') {
|
||||||
|
max-width: 2560px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-to('4k-40') {
|
||||||
|
max-width: 3800px;
|
||||||
|
}
|
||||||
|
// 当容器等于 4K 时,随之线性扩大
|
||||||
@include respond-to('4k') {
|
@include respond-to('4k') {
|
||||||
// 保持容器宽度占比:(3600 / 3840) * 100vw = 93.75vw
|
// 保持容器宽度占比:(3600 / 3840) * 100vw = 93.75vw
|
||||||
max-width: 93.75vw;
|
max-width: 93.75vw;
|
||||||
|
|||||||
Reference in New Issue
Block a user