Skip to content

Commit a334cfe

Browse files
committed
fix: 简单的一些调整
1 parent cee3898 commit a334cfe

14 files changed

+828
-12
lines changed

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,64 @@
22

33
基于“视窗宽度”动态调整CSS像素值
44

5+
## Idea
6+
7+
[掘金付费小册《现代 Web 布局 · 大漠 著》如何像素级完美还原一个可缩放的 UI 界面?章节的 PostCSS 插件实现](https://juejin.cn/book/7161370789680250917/section/7165496907714789407#heading-14)
8+
9+
### 重点摘录:
10+
11+
像素缩放计算的公式: `元素像素缩放计算值 = 设计稿上元素尺寸基数 x 100vw / 设计稿视窗宽度基数`;
12+
13+
* 设计稿上元素尺寸基数:指的是设计稿上 UI 元素尺寸的基数值,不带任何单位。比如设计稿上的某个 UI 元素的字号是 16px,那么代表 font-size 的基数值是16,该值也被称为理想尺寸值;
14+
* 100vw:代表访问应用设备当前视窗的宽度;
15+
* 设计稿视窗宽度基数:指的是设计稿的尺寸宽度,该宽度也被称为理想视窗宽度,比如目前移动端设计稿都是750px 宽度做的设计,那么这个理想视窗宽度(设计稿视窗宽度基数)就是 750;
16+
* 元素像素缩放计算值:指的就是 UI 元素根据计算公式得到的最终计算值,它会随着设备的当前视窗宽度值做缩放。
17+
18+
目前的像素缩放计算的公式,虽然能让 UI 元素尺寸大小根据视窗大小做出动态计算,从而实现完美的像素级缩放,但其还是略有不完美之处,因为不管视窗的大小,最终都会影响到计算值,也会影响到 UI 界面的最终效果。为此,我们可以给这种方式添加一把锁。即,使用 CSS 的 clamp() 函数来控制用户的最小视窗和最大视窗的宽度。
19+
20+
SCSS 函数实现:
21+
22+
```scss
23+
/**
24+
* @param {Number} $value - 理想尺寸基数,不带任何单位,设计稿对应的元素尺寸值,eg 设计稿元素宽度是500,$value = 500
25+
* @param {Number} $idealViewportWidth - 理想视窗宽度基数,不带单位,设计稿的宽度
26+
* @param {String} $min - 最小视窗宽度 * @param {String} $max - 最大视窗宽度
27+
**/
28+
@function scalePixelValue($value, $idealViewportWidth: 1600, $min: 320px, $max: 3480px) {
29+
@return calc( #{$value} * (clamp(#{$min}, 100vw, #{$max}) / #{$idealViewportWidth}))
30+
}
31+
```
32+
33+
## Install
34+
35+
```bash
36+
npm install postcss postcss-dynamic-pixel --save-dev
37+
```
38+
39+
## Configuration
40+
41+
```JavaScript
42+
// ./postcss.config.cjs
43+
const { dynamicPixel } = require('postcss-dynamic-pixel')
44+
45+
module.exports = {
46+
plugins: [
47+
dynamicPixel({
48+
idealViewportWidth: 750,
49+
currentViewportWidth: 100,
50+
minViewportWidth: 320,
51+
maxViewportWidth: 1440,
52+
})
53+
]
54+
}
55+
```
56+
57+
## Preview
58+
59+
```bash
60+
npm run example
61+
```
62+
563
## License
664

765
[MIT](./LICENSE) License © 2024-PRESENT [OSpoon](https://github.com/OSpoon)

example/App.vue

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<script setup lang="ts"></script>
2+
3+
<template>
4+
<div class="root">
5+
<div class="tab__content">
6+
<div class="card">
7+
<div class="card__media">
8+
<div class="media__object">
9+
<img src="https://picsum.photos/180/180?random=2" alt="">
10+
</div>
11+
</div>
12+
<div class="card__content">
13+
<h3 class="card__heading">
14+
星巴克猫爪杯八个字
15+
</h3>
16+
<p class="card__body">
17+
这是一段推荐文字九十一二三四五
18+
</p>
19+
<div class="card__footer">
20+
<div class="card__price">
21+
<div class="card__price--current">
22+
<span>&yen;</span> <strong>1</strong>
23+
</div>
24+
<del class="card__price--orgion">&yen;280.06</del>
25+
</div>
26+
<button class="card__button">
27+
1元抢
28+
</button>
29+
</div>
30+
<div class="card__badge">
31+
本周特推
32+
</div>
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
</template>
38+
39+
<style scoped>
40+
.tab__content {
41+
background: #ff9500;
42+
border-radius: 36px;
43+
padding: 22px;
44+
width: 702px;
45+
}
46+
47+
.card {
48+
display: flex;
49+
background: #ffffff;
50+
position: relative;
51+
box-shadow: 0 4px 4px 0 #ff5400, inset 0 -2px 0 0 rgba(255, 255, 255, 0.51),
52+
inset 0 -7px 6px 3px #ffcca4;
53+
border-radius: 38px;
54+
padding: 24px;
55+
}
56+
57+
.card__media {
58+
display: flex;
59+
justify-content: center;
60+
align-items: center;
61+
overflow: hidden;
62+
width: 170px;
63+
height: 170px;
64+
border-radius: 24px;
65+
margin-right: 20px;
66+
}
67+
68+
.card__media img {
69+
width: 100%;
70+
aspect-ratio: 1 / 1;
71+
display: block;
72+
border-radius: 24px;
73+
}
74+
75+
.card__content {
76+
flex: 1;
77+
min-width: 0;
78+
display: flex;
79+
flex-direction: column;
80+
}
81+
82+
.card__content > * {
83+
width: 100%;
84+
}
85+
86+
.card__heading {
87+
color: #000;
88+
overflow: hidden;
89+
white-space: nowrap;
90+
text-overflow: ellipsis;
91+
font-weight: 900;
92+
font-size: 30px;
93+
margin-bottom: 6px;
94+
}
95+
96+
.card__body {
97+
color: #5b5b5b;
98+
font-size: 24px;
99+
}
100+
101+
.card__footer {
102+
display: flex;
103+
margin-top: auto;
104+
align-items: flex-end;
105+
justify-content: space-between;
106+
}
107+
108+
button {
109+
display: inline-flex;
110+
justify-content: center;
111+
align-items: center;
112+
font-weight: 600;
113+
border: none 0;
114+
color: #fff;
115+
border-radius: 10rem;
116+
background-image: linear-gradient(180deg, #f74b4b 0%, #e32828 99%);
117+
min-width: 210px;
118+
min-height: 62px;
119+
padding: 0 20px;
120+
font-size: 26px;
121+
}
122+
123+
.card__price {
124+
display: flex;
125+
color: #5b5b5b;
126+
align-items: flex-end;
127+
line-height: 1;
128+
font-size: 22px;
129+
}
130+
131+
.card__price--current {
132+
font-weight: 600;
133+
color: #ff1300;
134+
font-size: 24px;
135+
}
136+
137+
.card__price--current span {
138+
margin-right: -4px;
139+
}
140+
141+
.card__price--current strong {
142+
font-size: 46px;
143+
}
144+
145+
.card__price--orgion {
146+
text-decoration: none;
147+
position: relative;
148+
margin-left: 8px;
149+
bottom: 0.1325em;
150+
}
151+
152+
.card__price--orgion::after {
153+
content: "";
154+
position: absolute;
155+
left: 0;
156+
right: 0;
157+
background-color: currentColor;
158+
z-index: 2;
159+
top: 50%;
160+
transform: translate3d(0, -50%, 0);
161+
height: 2px;
162+
}
163+
164+
.card__badge {
165+
position: absolute;
166+
z-index: 2;
167+
top: 0;
168+
left: 0;
169+
display: inline-flex;
170+
justify-content: center;
171+
align-items: center;
172+
background-image: linear-gradient(180deg, #f74b4b 0%, #e32828 99%);
173+
font-weight: 600;
174+
font-size: 24px;
175+
border-radius: 36px 0 36px 0;
176+
max-width: 146px;
177+
min-height: 42px;
178+
}
179+
</style>

example/assets/vue.svg

Lines changed: 1 addition & 0 deletions
Loading

example/main.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createApp } from 'vue'
2+
import './style.css'
3+
import App from './App.vue'
4+
5+
createApp(App).mount('#app')

example/style.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
* {
2+
margin: 0;
3+
padding: 0;
4+
box-sizing: border-box;
5+
}
6+
7+
body {
8+
width: 100vw;
9+
min-height: 100vh;
10+
display: flex;
11+
justify-content: center;
12+
background-color: #ffce00;
13+
color: #fff;
14+
}

example/vite-env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="vite/client" />

index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + Vue + TS</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/example/main.ts"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)