7月6日笔记
1.单复选
代码演示:
点击查看代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文字获得焦点 + 一键全选</title>
<style>
/* ----- 核心:文字获得焦点样式 ----- */
.option-group label {
display: inline-block;
margin: 8px 16px 8px 0;
padding: 6px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: all 0.2s;
}
/* 当内部的 input 获得焦点时,文字变色加粗 */
.option-group label:focus-within {
color: #0066ff;
font-weight: bold;
background-color: #f0f7ff;
}
/* 输入框聚焦时的辅助样式(可选) */
.option-group input:focus {
outline: 2px solid #0066ff;
outline-offset: 2px;
}
/* ----- 页面布局 ----- */
body {
font-family: system-ui, sans-serif;
padding: 40px;
background: #f9f9f9;
}
.container {
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
max-width: 550px;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px solid #eee;
}
.hint {
margin-top: 20px;
color: #888;
font-size: 14px;
}
kbd {
background: #eee;
padding: 0 6px;
border-radius: 3px;
font-size: 13px;
}
/* 全选行样式 */
.select-all-row {
margin-bottom: 12px;
padding: 6px 0;
border-bottom: 1px dashed #ddd;
}
.select-all-row label {
font-weight: 600;
color: #333;
}
</style>
</head>
<body>
<div class="container">
<h3>点击文字或按 Tab 键聚焦</h3>
<!-- ===== 单选组 ===== -->
<div class="option-group">
<p><strong>单选:</strong></p>
<label>
<input type="radio" name="gender" value="男"> 男
</label>
<label>
<input type="radio" name="gender" value="女"> 女
</label>
</div>
<hr>
<!-- ===== 复选框组(带全选) ===== -->
<div class="option-group">
<p><strong>复选框:</strong></p>
<!-- 全选控制行 -->
<div class="select-all-row">
<label>
<input type="checkbox" id="selectAll"> ✅ 全选
</label>
</div>
<!-- 各爱好选项 -->
<label>
<input type="checkbox" class="hobby" value="读书"> 读书
</label>
<label>
<input type="checkbox" class="hobby" value="运动"> 运动
</label>
<label>
<input type="checkbox" class="hobby" value="音乐"> 音乐
</label>
<label>
<input type="checkbox" class="hobby" value="旅行"> 旅行
</label>
</div>
<div class="hint">
✅ 点击文字或按 <kbd>Tab</kbd> 键,聚焦的文字会变蓝加粗。<br>
✅ 勾选“全选”可一键控制所有爱好。
</div>
</div>
<script>
(function() {
const selectAll = document.getElementById('selectAll');
const hobbyCheckboxes = document.querySelectorAll('.hobby');
// 更新全选状态(根据子项同步)
function updateSelectAll() {
const allChecked = Array.from(hobbyCheckboxes).every(cb => cb.checked);
selectAll.checked = allChecked;
}
// 全选复选框变化时,同步所有子项
selectAll.addEventListener('change', function() {
hobbyCheckboxes.forEach(cb => {
cb.checked = selectAll.checked;
});
// 手动触发一次更新(其实已经一致,但为了保险)
updateSelectAll();
});
// 每个子项变化时,更新全选状态
hobbyCheckboxes.forEach(cb => {
cb.addEventListener('change', updateSelectAll);
});
// 初始同步一次
updateSelectAll();
})();
</script>
</body>
</html>
效果图:

2.flex弹性布局
代码演示:
点击查看代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Flex 弹性布局 · 交互式演示</title>
<style>
/* ----- 全局样式 ----- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
background: #f0f5fb;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 2rem 1rem;
}
.container {
max-width: 1100px;
width: 100%;
background: #ffffff;
border-radius: 2rem;
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.07);
padding: 2rem 2rem 2.5rem;
}
h1 {
font-weight: 600;
font-size: 1.8rem;
color: #0b1e2e;
margin-bottom: 0.2rem;
}
.sub {
color: #647a8f;
font-size: 0.95rem;
margin-bottom: 1.8rem;
border-left: 4px solid #b6ccdf;
padding-left: 1rem;
}
/* ----- 演示区域 ----- */
.demo-area {
background: #fafdff;
border-radius: 1.2rem;
border: 1px solid #e4edf6;
padding: 1.5rem;
margin-bottom: 1.8rem;
}
/* Flex 容器 */
.flex-container {
display: flex;
background: #eef3f9;
border-radius: 0.8rem;
padding: 1rem;
min-height: 220px;
gap: 0.6rem;
transition: all 0.25s ease;
border: 2px dashed #b6ccdf;
flex-wrap: nowrap; /* 默认,由控制覆盖 */
align-content: stretch;
}
.flex-item {
background: #1f3a5f;
color: #fff;
font-weight: 500;
border-radius: 0.6rem;
padding: 0.8rem 0.5rem;
text-align: center;
min-width: 50px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.25s ease;
font-size: 0.9rem;
flex: 0 1 auto; /* 默认由控制覆盖 */
}
.flex-item:nth-child(1) { background: #2a5a7a; }
.flex-item:nth-child(2) { background: #3d7ca3; }
.flex-item:nth-child(3) { background: #5b9abf; }
.flex-item:nth-child(4) { background: #7fb4d4; }
.flex-item:nth-child(5) { background: #a8cce3; color: #1a2b3e; }
/* ----- 控制面板 ----- */
.controls {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem 1.5rem;
background: #f8fafc;
padding: 1.2rem 1.5rem;
border-radius: 1.2rem;
border: 1px solid #e4edf6;
margin-top: 0.5rem;
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.control-group label {
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #4f657c;
}
.control-group select,
.control-group input[type="range"] {
padding: 0.3rem 0.5rem;
border-radius: 0.5rem;
border: 1px solid #d0dce8;
background: #fff;
font-size: 0.85rem;
cursor: pointer;
outline: none;
}
.control-group select:focus,
.control-group input:focus {
border-color: #1f3a5f;
}
.control-group .value-indicator {
font-size: 0.8rem;
color: #1f3a5f;
font-weight: 500;
margin-top: 0.1rem;
}
.control-group input[type="range"] {
width: 100%;
}
/* 项目单独控制 */
.item-controls {
margin-top: 1.2rem;
display: flex;
flex-wrap: wrap;
gap: 0.8rem 1.5rem;
background: #ffffff;
padding: 1rem 1.2rem;
border-radius: 0.8rem;
border: 1px solid #e4edf6;
}
.item-controls .control-group {
flex: 1 0 150px;
}
.item-controls .control-group select {
background: #f9fcff;
}
.badge {
display: inline-block;
background: #dce8f2;
padding: 0.1rem 0.6rem;
border-radius: 20px;
font-size: 0.7rem;
color: #1f3a5f;
font-weight: 600;
}
/* 响应式 */
@media (max-width: 700px) {
.container { padding: 1.2rem; }
.controls { grid-template-columns: 1fr 1fr; }
.item-controls { flex-direction: column; }
}
@media (max-width: 480px) {
.controls { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="container">
<h1>🧩 Flex 弹性布局 · 交互演示</h1>
<div class="sub">调整下方属性,实时观察 Flex 容器和项目的变化</div>
<!-- Flex 容器展示 -->
<div class="demo-area">
<div class="flex-container" id="flexContainer">
<div class="flex-item" id="item1">1</div>
<div class="flex-item" id="item2">2</div>
<div class="flex-item" id="item3">3</div>
<div class="flex-item" id="item4">4</div>
<div class="flex-item" id="item5">5</div>
</div>
</div>
<!-- 容器控制面板 -->
<div class="controls" id="containerControls">
<div class="control-group">
<label>flex-direction</label>
<select id="flexDirection">
<option value="row">row</option>
<option value="row-reverse">row-reverse</option>
<option value="column">column</option>
<option value="column-reverse">column-reverse</option>
</select>
</div>
<div class="control-group">
<label>flex-wrap</label>
<select id="flexWrap">
<option value="nowrap">nowrap</option>
<option value="wrap">wrap</option>
<option value="wrap-reverse">wrap-reverse</option>
</select>
</div>
<div class="control-group">
<label>justify-content</label>
<select id="justifyContent">
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-between">space-between</option>
<option value="space-around">space-around</option>
<option value="space-evenly">space-evenly</option>
</select>
</div>
<div class="control-group">
<label>align-items</label>
<select id="alignItems">
<option value="stretch">stretch</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="baseline">baseline</option>
</select>
</div>
<div class="control-group">
<label>align-content</label>
<select id="alignContent">
<option value="stretch">stretch</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-between">space-between</option>
<option value="space-around">space-around</option>
</select>
</div>
<div class="control-group">
<label>gap (间距) <span id="gapValue">0.6rem</span></label>
<input type="range" id="gapSlider" min="0" max="2" step="0.1" value="0.6" />
</div>
</div>
<!-- 项目单独控制 -->
<div class="item-controls">
<div class="control-group">
<label>项目 1 flex-grow</label>
<select id="grow1">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="control-group">
<label>项目 2 flex-grow</label>
<select id="grow2">
<option value="0">0</option>
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="control-group">
<label>项目 3 flex-grow</label>
<select id="grow3">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
</div>
<div class="control-group">
<label>项目 4 flex-grow</label>
<select id="grow4">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="control-group">
<label>项目 5 flex-grow</label>
<select id="grow5">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="control-group">
<label><span class="badge">align-self</span> 项目 3</label>
<select id="alignSelf3">
<option value="auto">auto</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="baseline">baseline</option>
<option value="stretch">stretch</option>
</select>
</div>
</div>
<div style="margin-top: 1.5rem; font-size: 0.85rem; color: #5c738a; text-align: center; border-top: 1px solid #e4edf6; padding-top: 1rem;">
💡 提示:调整容器属性影响所有子项,项目 flex-grow 控制剩余空间分配,align-self 单独覆盖 align-items。
</div>
</div>
<script>
(function() {
const container = document.getElementById('flexContainer');
// ----- 容器控制元素 -----
const flexDirection = document.getElementById('flexDirection');
const flexWrap = document.getElementById('flexWrap');
const justifyContent = document.getElementById('justifyContent');
const alignItems = document.getElementById('alignItems');
const alignContent = document.getElementById('alignContent');
const gapSlider = document.getElementById('gapSlider');
const gapValue = document.getElementById('gapValue');
// ----- 项目控制元素 -----
const grow1 = document.getElementById('grow1');
const grow2 = document.getElementById('grow2');
const grow3 = document.getElementById('grow3');
const grow4 = document.getElementById('grow4');
const grow5 = document.getElementById('grow5');
const alignSelf3 = document.getElementById('alignSelf3');
// 获取所有项目
const items = [
document.getElementById('item1'),
document.getElementById('item2'),
document.getElementById('item3'),
document.getElementById('item4'),
document.getElementById('item5')
];
const growSelectors = [grow1, grow2, grow3, grow4, grow5];
// ----- 更新容器样式 -----
function updateContainer() {
container.style.flexDirection = flexDirection.value;
container.style.flexWrap = flexWrap.value;
container.style.justifyContent = justifyContent.value;
container.style.alignItems = alignItems.value;
container.style.alignContent = alignContent.value;
const gap = parseFloat(gapSlider.value);
container.style.gap = gap + 'rem';
gapValue.textContent = gap.toFixed(1) + 'rem';
}
// ----- 更新项目样式 -----
function updateItems() {
// 设置 flex-grow
items.forEach((item, index) => {
const val = parseInt(growSelectors[index].value, 10);
item.style.flexGrow = val;
// 保留 flex-shrink 和 flex-basis 默认
// 为了效果,我们设置 flex-basis: auto,让 grow 起作用
item.style.flexBasis = 'auto';
// 重置 flex 简写,避免冲突
item.style.flex = `${val} 1 auto`;
});
// 单独设置项目3的 align-self
const selfVal = alignSelf3.value;
items[2].style.alignSelf = selfVal;
}
// ----- 绑定事件 -----
function bindControls() {
const containerControls = [
flexDirection, flexWrap, justifyContent,
alignItems, alignContent, gapSlider
];
containerControls.forEach(el => {
el.addEventListener('change', updateContainer);
el.addEventListener('input', updateContainer); // 支持滑块实时
});
const itemControls = [...growSelectors, alignSelf3];
itemControls.forEach(el => {
el.addEventListener('change', updateItems);
});
// 额外:容器属性变化时也要重新应用项目样式(因为可能影响布局)
// 但项目样式独立,所以分别调用
// 初始更新
updateContainer();
updateItems();
// 当容器属性变化时,项目样式不变,但可能因为容器尺寸变化而影响,但项目样式依然独立
// 所以不需要额外联动
}
bindControls();
})();
</script>
</body>
</html>
效果图:

浙公网安备 33010602011771号