Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
內(nèi)容首發(fā)于工粽號(hào):程序員大澈,每日分享一段優(yōu)質(zhì)代碼片段,歡迎關(guān)注和投稿!
大家好,我是大澈!
本文約 800+ 字,整篇閱讀約需 1 分鐘。
今天分享一段優(yōu)質(zhì) CSS 代碼片段,輕松實(shí)現(xiàn)一鍵切換主題顏色,在任何項(xiàng)目中都可用。
老規(guī)矩,先閱讀代碼片段并思考,再看代碼解析再思考,最后評(píng)論區(qū)留下你的見解!
[data-theme='default'] {
--font-primary: #fff;
--background-main: #0678be;
}
[data-theme='black'] {
--font-primary: #fff;
--background-main: #393939;
}
<html lang="en" data-theme="default"></html>
body {
color: var(--font-primary);
background-color: var(--background-main);
}
分享原因
這段代碼可以輕松實(shí)現(xiàn)網(wǎng)頁主題的切換,且在各種項(xiàng)目中通用。
先定義不同主題的 CSS 變量,再通過 JavaScript 動(dòng)態(tài)更改 data-theme 屬性,從而實(shí)現(xiàn)頁面樣式的動(dòng)態(tài)變化。
這種方法不僅簡(jiǎn)化了主題管理,還提高了代碼的可讀性和維護(hù)性,是我們項(xiàng)目中一般且常用的實(shí)現(xiàn)方式之一。
代碼解析
1. 定義主題變量
CSS變量:聲明自定義CSS屬性,它包含的值可以在整個(gè)文檔中重復(fù)使用。屬性名需要以兩個(gè)減號(hào)(--)開始,屬性值則可以是任何有效的 CSS 值。
CSS屬性選擇器:匹配具有特定屬性或?qū)傩灾档脑亍@鏪data-theme='black'],將選擇所有 data-theme 屬性值為 'black' 的元素。
使用 [data-theme='default'] 和 [data-theme='black'] 選擇器,根據(jù) data-theme 屬性的值定義不同的主題樣式。
定義了兩個(gè) CSS 變量 --font-primary 和 --background-main,分別表示字體顏色和背景顏色。
2. 指定默認(rèn)主題
在 <html> 元素上添加 data-theme="default",指定默認(rèn)主題為 default 。
后面用 js 動(dòng)態(tài)切換 data-theme 屬性值,然后 CSS 屬性選擇器將自動(dòng)選擇對(duì)應(yīng)的 CSS 變量。
3. 應(yīng)用 CSS 變量
Var函數(shù):用于使用 CSS 變量。第一個(gè)參數(shù)為 CSS 變量名稱,第二個(gè)可選參數(shù)作為默認(rèn)值。
使用 var(--font-primary) 和 var(--background-main) 來引用之前定義的 CSS 變量。
這里設(shè)置 body 元素的 color 和 background-color 屬性,分別引用 --font-primary 和 --background-main 變量,在項(xiàng)目中按需設(shè)置對(duì)應(yīng)的元素即可。
子頁面把整個(gè)頁面做絕對(duì)定位,覆蓋整個(gè)屏幕,子父頁面將 router-view 用 transition 套起來,并加上過渡動(dòng)畫就可以啦。
代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <title>Document</title> <style> * { padding: 0; margin: 0; } html, body, #app { width: 100%; height: 100%; } .one { height: 100%; background-color: yellow; } .two { background-color: tomato; position: fixed; top: 0; bottom: 0; left: 0; right: 0; } .three { background-color: #ffe69f; position: fixed; top: 0; bottom: 0; left: 0; right: 0; } .v-enter-active, .v-leave-active { transition: all 0.3s; } .v-enter, .v-leave-to { transform: translateX(100%); } </style> </head> <body> <div id="app"> <div class="one"> <p> <router-link to="/foo">下一層</router-link> </p> <h1>第一層</h1> </div> <transition> <router-view></router-view> </transition> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script> const Foo = { template: ` <div class="whole-page two"> <router-link to="/foo/bar">下一層</router-link> <router-link to="/">返回</router-link> <h1>第二層</h1> <transition> <router-view></router-view> </transition> </div> ` } const Bar = { template: ` <div class="whole-page three"> <router-link to="/foo">返回</router-link> <h1>第三層</h1> <transition> <router-view></router-view> </transition> </div> ` } const routes = [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar } ] } ] const router = new VueRouter({ routes }) const app = new Vue({ router }).$mount('#app') </script> </body> </html>
效果:
有一個(gè)問題需要注意一下,
我們知道,在應(yīng)用transform屬性的時(shí)候,fixed定位會(huì)變成absolute。
這里,頁面轉(zhuǎn)換的時(shí)候,就變成了相對(duì)translation定位。所以如果子頁面中有絕對(duì)定位的話,移動(dòng)的過程中頁面會(huì)變形。
簡(jiǎn)單舉個(gè)栗子,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <title>Document</title> <style> * { padding: 0; margin: 0; } html, body, #app { width: 100%; height: 100%; } #app { padding-top: 50px; } .one { height: 100%; background-color: yellow;} .two { background-color: tomato; position: fixed; top: 100px; bottom: 0; left: 0; right: 0; }.v-enter-active, .v-leave-active { transition: all 0.3s; } .v-enter, .v-leave-to { transform: translateX(100%); } header { height: 50px; background-color: #000; width: 100%; position: fixed; top: 0; color: #fff; line-height: 50px; text-align: center; } .two header { top: 50px; background-color: #666; } </style> </head> <body> <div id="app"> <header>我是一個(gè)標(biāo)題</header> <div class="one"> <p> <router-link to="/foo">下一層</router-link> </p> <h1>第一層</h1> <transition> <router-view></router-view> </transition> </div> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script> const Foo = { template: ` <div class="whole-page two"> <router-link to="/">返回</router-link> <header>我也是一個(gè)標(biāo)題</header> <h1>第二層</h1> <transition> <router-view></router-view> </transition> </div> ` } const routes = [ { path: '/foo', component: Foo } ] const router = new VueRouter({ routes }) const app = new Vue({ router }).$mount('#app') </script> </body> </html>
看下效果:
OKOK,反正就是這種bug嘛。
解決辦法就是,就是,盡量讓頁面fixed定位都是0 0 0 0,然后偏移用padding實(shí)現(xiàn)。
大概吧……反正我是這么解決的……
比如上面那個(gè)可以把CSS改成這樣解決問題。
* { padding: 0; margin: 0; } html, body, #app { width: 100%; height: 100%; } #app { padding-top: 50px; } .one { height: 100%; background-color: yellow;} .two { background-color: tomato; position: fixed; top: 0; padding-top: 100px; bottom: 0; left: 0; right: 0; }.v-enter-active, .v-leave-active { transition: all 0.3s; } .v-enter, .v-leave-to { transform: translateX(100%); } header { height: 50px; background-color: #000; width: 100%; position: fixed; top: 0; color: #fff; line-height: 50px; text-align: center; z-index: 100; } .two header { top: 50px; background-color: #666; }
嗯嗯 還有一個(gè)問題,還有個(gè)滑動(dòng)穿透的問題,(真開心! 這么多問題!
我再舉個(gè)栗子,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <title>Document</title> <style> * { padding: 0; margin: 0; } html, body, #app { width: 100%; height: 100%; } .one { min-height: 100%; background-color: yellow;} .two { background-color: tomato; position: fixed; top: 0; bottom: 0; left: 0; right: 0; } .three { background-color: #ffe69f; position: fixed; top: 50px; bottom: 0; left: 0; right: 0; } .v-enter-active, .v-leave-active { transition: all 0.3s; } .v-enter, .v-leave-to { transform: translateX(100%); } </style> </head> <body> <div id="app"> <div class="one"> <p> <router-link to="/foo">下一層</router-link> </p> <h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1> <h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1> <h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1><h1>第一層</h1> <transition> <router-view></router-view> </transition> </div> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script> const Foo = { template: ` <div class="whole-page two"> <router-link to="/">返回</router-link> <h1>第二層</h1> <transition> <router-view></router-view> </transition> </div> ` } const routes = [ { path: '/foo', component: Foo } ] const router = new VueRouter({ routes }) const app = new Vue({ router }).$mount('#app') </script> </body> </html>
看效果,第二頁的高度明明就是視窗的高度,但是它有一個(gè)滾動(dòng)條,實(shí)際上那是第一個(gè)頁面的滾動(dòng)條。
網(wǎng)上找了好多方法,一一試了,全部不生效。(當(dāng)然很有可能是我的方法不對(duì)。
最后沒辦法只有找最笨的方法啦,就是通過 v-if 把父頁面不顯示就好了。
當(dāng)然不能直接不顯示,因?yàn)閯?dòng)畫還沒結(jié)束父元素就空白了呀!setTimeout 就好了……
具體代碼就不寫了,這個(gè)應(yīng)該很容易理解。
以下是總結(jié)出來最全前端框架視頻,包含: javascript/vue/react/angualrde/express/koa/webpack 等學(xué)習(xí)資料。
HTML+CSS3+JS創(chuàng)意設(shè)計(jì)——打造炫酷滑動(dòng)登錄頁面
**引言:探索交互之美**
在Web開發(fā)的世界里,優(yōu)秀的用戶體驗(yàn)往往始于一個(gè)精心設(shè)計(jì)的登錄界面。HTML5、CSS3以及JavaScript的結(jié)合讓我們能夠創(chuàng)造出極具創(chuàng)意與個(gè)性化的滑動(dòng)登錄頁面,讓用戶在首次接觸應(yīng)用時(shí)就能留下深刻印象。本篇文章將詳細(xì)介紹如何利用基礎(chǔ)的HTML+CSS3+JS技術(shù),從零開始打造一款令人眼前一亮的滑動(dòng)登錄頁面,并通過詳細(xì)的代碼實(shí)例解析,帶領(lǐng)您領(lǐng)略前端交互設(shè)計(jì)的魅力。
---
### **一、搭建基礎(chǔ)HTML結(jié)構(gòu)**
**標(biāo)題:** 構(gòu)建骨骼——登錄表單的基礎(chǔ)布局
首先,我們需要構(gòu)建一個(gè)簡(jiǎn)潔明了的HTML結(jié)構(gòu),包括用戶名輸入框、密碼輸入框、登錄按鈕以及可選的注冊(cè)鏈接。為了實(shí)現(xiàn)滑動(dòng)效果,我們還將引入一個(gè)容器元素來包裹整個(gè)登錄區(qū)域。
```html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>滑動(dòng)登錄頁面</title>
<!-- 引入外部CSS和JS文件 -->
<link rel="stylesheet" href="styles.css">
<script src="scripts.js" defer></script>
</head>
<body>
<div id="login-slider">
<form action="#" class="login-form">
<input type="text" placeholder="用戶名" required>
<input type="password" placeholder="密碼" required>
<button type="submit">登錄</button>
<a href="#">忘記密碼?</a>
<a href="#">立即注冊(cè)</a>
</form>
</div>
</body>
</html>
```
---
### **二、CSS3魔法——樣式與動(dòng)畫**
**標(biāo)題:** 點(diǎn)綴肌膚——賦予登錄表單靈動(dòng)之感
接下來,我們將使用CSS3為登錄表單添加樣式,并利用`@keyframes`規(guī)則定義滑動(dòng)動(dòng)畫效果。同時(shí),我們還需要保證登錄表單在不同設(shè)備上具有良好的響應(yīng)式布局。
```css
/* styles.css */
body {
margin: 0;
background-color: #f0f0f0;
}
#login-slider {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
height: auto;
background-color: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.login-form {
display: flex;
flex-direction: column;
padding: 20px;
animation: slideIn 1s ease-in-out forwards;
}
/* 定義滑動(dòng)動(dòng)畫 */
@keyframes slideIn {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(0);
}
}
/* 登錄表單元素樣式 */
input[type="text"],
input[type="password"] {
margin-bottom: 10px;
padding: 10px;
border: none;
border-radius: 5px;
}
button {
cursor: pointer;
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
text-transform: uppercase;
font-weight: bold;
}
/* 響應(yīng)式布局 */
@media screen and (max-width: 768px) {
#login-slider {
width: 90%;
}
}
```
---
### **三、JavaScript增強(qiáng)交互**
**標(biāo)題:** 賦予靈魂——用JavaScript實(shí)現(xiàn)滑動(dòng)觸發(fā)與驗(yàn)證邏輯
現(xiàn)在我們要借助JavaScript來控制登錄表單的滑動(dòng)行為,例如當(dāng)用戶點(diǎn)擊某個(gè)鏈接或者頁面加載完成后自動(dòng)觸發(fā)滑動(dòng)動(dòng)畫。同時(shí),可以增加一些簡(jiǎn)單的表單驗(yàn)證功能。
```javascript
// scripts.js
document.addEventListener('DOMContentLoaded', () => {
// 頁面加載完成后執(zhí)行滑動(dòng)動(dòng)畫
const loginSlider = document.getElementById('login-slider');
loginSlider.classList.add('slide-active');
// 表單提交事件處理,此處僅為示例,實(shí)際場(chǎng)景下需加入真實(shí)驗(yàn)證邏輯
const form = document.querySelector('.login-form');
form.addEventListener('submit', (event) => {
event.preventDefault(); // 阻止默認(rèn)提交行為
const username = form.querySelector('input[type="text"]').value;
const password = form.querySelector('input[type="password"]').value;
// 實(shí)現(xiàn)簡(jiǎn)單驗(yàn)證邏輯,如為空檢查
if (!username || !password) {
alert('用戶名和密碼不能為空!');
} else {
// 這里可以替換為真實(shí)的登錄請(qǐng)求邏輯
console.log('正在登錄...', username, password);
}
});
});
```
---
### **四、創(chuàng)意無限——拓展與優(yōu)化**
**標(biāo)題:** 持續(xù)創(chuàng)新——更多滑動(dòng)登錄頁面的設(shè)計(jì)思路與實(shí)踐
除了上述基本的滑動(dòng)登錄形式,還可以進(jìn)一步豐富設(shè)計(jì),比如:
- 添加進(jìn)度條指示登錄滑動(dòng)完成度;
- 使用CSS變量實(shí)現(xiàn)自定義主題切換;
- 結(jié)合SVG圖標(biāo)增加視覺吸引力;
- 通過IntersectionObserver API實(shí)現(xiàn)視口可見時(shí)自動(dòng)滑動(dòng);
- 配合AJAX技術(shù)實(shí)現(xiàn)實(shí)時(shí)驗(yàn)證和無刷新登錄。
---
**結(jié)語:**
通過這次對(duì)HTML+CSS3+JS組合技術(shù)的探索,我們不僅成功地制作出了一個(gè)富有創(chuàng)意的滑動(dòng)登錄頁面,還展現(xiàn)了前端技術(shù)在交互設(shè)計(jì)中的無限可能性。學(xué)習(xí)并靈活運(yùn)用這些基礎(chǔ)知識(shí),可以讓您的Web應(yīng)用更加生動(dòng)有趣,從而更好地吸引和留住用戶。持續(xù)關(guān)注前端技術(shù)的最新發(fā)展,不斷挑戰(zhàn)自我,用代碼書寫更美好的Web世界。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。