HTML、CSS 和 JavaScript 的小技巧

2025-05-27

HTML、CSS 和 JavaScript 的小技巧

极客的东西

本文最初发表于medium.com

一份很棒的 HTML、CSS 和 JavaScript 入门指南列表,包含日常使用的基本概念。欢迎留言分享你自己的方法 :)

使用 CSS 禁用所有内容

CSS

.disabled {
  filter: grayscale(1);
  pointer-events: none;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

将数组拆分成不可变的块

JS

const array = [1, 2, 3, 4]
const size = 3
const new_array = array.reduce((acc, a, i) => {
  i % size ? acc[parseInt(i / size)].push(a) : acc.push([a])
  return acc
}, [])
Enter fullscreen mode Exit fullscreen mode

甚至更短:

const new_array = array.reduce((acc, a, i) =>
  i % size ? acc : [...acc, array.slice(i, i + size)], [])
Enter fullscreen mode Exit fullscreen mode

请记住,开始使用const,如果您需要更改其值,则使用let并尽可能避免var

在此处查看 JSFiddle

保存和加载日期

始终将日期时间保存在 UTC ISO 中,并使用本地 ISO 将其加载到用户界面。使用原生小部件可避免日期格式偏好设置(例如中端、小端等)。

HTML

<input type="datetime-local">
<button>Save</button>
<button>Load</button>
Enter fullscreen mode Exit fullscreen mode

JS

$button_save.onclick = () =>
  localStorage.setItem('datetime', $input.value && 
  new Date($input.value).toISOString())

$button_load.onclick = () =>
  $input.value = localStorage.getItem('datetime') &&
  toLocalISOString(new Date(localStorage.getItem('datetime')))
  .slice(0, -8)

function toLocalISOString(d) {
  const offset = d.getTimezoneOffset()
  return new Date(
    d.getFullYear(),
    d.getMonth(),
    d.getDate(),
    d.getHours(),
    d.getMinutes() - offset,
    d.getSeconds(),
    d.getMilliseconds()).toISOString()
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

我建议使用sessionStoragelocalStorage。如果不是绝对必要,请勿滥用 Cookie。如果您需要更多本地存储空间,可以使用 IndexedDB。

通过单击标题选择 HTML 表格列

JS

document.querySelectorAll('th').forEach($th => 
  $th.onclick = event => {
    document.querySelectorAll(`td:nth-of-type(${event.currentTarget
      .cellIndex + 1})`)
    .forEach($td => $td.classList.toggle('selected'))
 })
Enter fullscreen mode Exit fullscreen mode

请记住,onclick始终覆盖前一个函数(如果有的话),用于addEventListener()多个函数。

在此处查看 JSFiddle

解构时重命名

我们将在对对象数组进行排序时重命名时间属性
。JS

let times = [
  {name:'dog', time: '10:23'}, 
  {name: 'laundry', time: '09:34'}, 
  {name: 'work', time: '11:00'}]

times.sort(({ time: a }, { time: b }) => a < b ? -1 : a > b ? 1 : 0)
Enter fullscreen mode Exit fullscreen mode

记住,sort()改变原始数组。

在此处查看 JSFiddle

自动完成下拉菜单

你用过 jQuery UI 或 Bootstrap 第三方选项的自动完成下拉菜单吗?简直一团糟。

幸运的是,几年前我们就得到了一个期待已久的解决方案:原生 HTML5 自动完成下拉菜单datalist。这是一个支持所有设备的轻量级标准。

HTML

<input list="series">
<datalist id="series">
  <option value="Adventure Time">
  <option value="Rick and Morty">
  <option value="Game of Thrones">
  <option value="Planet Earth 2">
</datalist>
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

节省您的工具时间和依赖性,尽可能少地使用库和框架!

使用 CSS Grid 实现真正轻松的响应

CSS Grid 是处理响应能力最简单、最干净、最强大的方法,这是近年来发展起来的一种全新方法,可以随时使用。

CSS Grid 改变了您以前布局文档的方式,不再需要使用 divitis(大量的 div)和 JavaScriptdiv根据屏幕改变位置(Bootstrap 现在所做的),您可以使用纯 CSS 网格布局,只使用有意义的 div,并且不受文档源顺序的影响。

您不需要接触 HTML 或 JavaScript,不需要 Bootstrap 甚至复杂的 CSS 规则,您在 CSS 中看到的内容就是您在屏幕上得到的内容。

HTML

<div class="grid">
  <div class="name">Name</div>
  <div class="score">Score</div>
  <div class="skills">Skills</div>
  <div class="chart">Chart</div>
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

.grid {
   display: grid;
   grid-template-areas: 
   "name" 
   "score" 
   "skills" 
   "chart";
}
@media only screen and (min-width: 500px) {
  .grid {
    grid-template-areas:
    "name skills" 
    "score skills"
    "chart chart";
  }
}
.name {
  grid-area: name;
}
.score {
  grid-area: score;
}
.skills {
  grid-area: skills;
}
.chart {
  grid-area: chart;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

我建议你做这些例子

像我一样爱上网格模板❤

移动用户界面的各个部分而不影响交互

HTML

<ul>
  <li>
    <button id="up">Up</button>
    <button id="down">Down</button>
  </li>
  <li>Nothing</li>
  <li>Nothing</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

JS

document.querySelector('#up').onclick = e => {
  const $li = e.target.parentElement
  if ($li.previousElementSibling)
    $li.parentElement.insertBefore($li, $li.previousElementSibling)
}

document.querySelector('#down').onclick = e => {
  const $li = e.target.parentElement
  if ($li.nextElementSibling)
    $li.parentElement.insertBefore($li.nextElementSibling, $li)
}
Enter fullscreen mode Exit fullscreen mode

请记住,target是什么触发了事件,并且currentTarget是什么分配了监听器。

在此处查看 JSFiddle

HTML 输入 24 小时格式的时间

依赖原生 HTML 小部件,无需依赖第三方库。然而,有时会有一些限制。如果您曾经处理过 HTMLinput时间,并且了解它的含义,请尝试设置最大或最小小时/分钟,以及/或者将 12 小时制更改为 24 小时制,反之亦然。目前为止,避免麻烦的一个好方法是使用两个数字类型的输入框和少量 JS。

HTML

<div>
  <input type="number" min="0" max="23" placeholder="23">:
  <input type="number" min="0" max="59" placeholder="00">
</div>
Enter fullscreen mode Exit fullscreen mode

CSS

div {
  background-color: white;
  display: inline-flex;
  border: 1px solid #ccc;
  color: #555;
}
input {
   border: none;
   color: #555;
   text-align: center;
   width: 60px;
 }
Enter fullscreen mode Exit fullscreen mode

JS

document.querySelectorAll('input[type=number]')
  .forEach(e => e.oninput = () => {
    if (e.value.length >= 2) e.value = e.value.slice(0, 2)
    if (e.value.length == 1) e.value = '0' + e.value
    if (!e.value) e.value = '00'
 })
Enter fullscreen mode Exit fullscreen mode

请记住,==双重比较来判断是否相等,===三重比较来判断是否相等和类型。

如果要检查变量是否存在undefined,只需使用三重比较即可a === undefined,对于 也一样null。如果要检查它是否存在,请使用typeof a != 'undefined'

在此处查看 JSFiddle

不使用可变变量循环 n 次

JS

[...Array(10).keys()]
  .reduce((sum, e) => sum + `<li>${e}</li>`, '')
Enter fullscreen mode Exit fullscreen mode

也喜欢这个:

[...Array(10)]
  .reduce((sum, _, i) => sum + `<li>${i}</li>`, '')
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

水平和垂直居中

忘记任何复杂的方法,只需使用 Flexbox 并在容器中设置水平中心和垂直中心。

CSS

body {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
div {
  background-color: #555;
  width: 100px;
  height: 100px;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

异步获取

fetch()与异步函数一起使用。

JS

async function async_fetch(url) {
  let response = await fetch(url)
  return await response.json()
}

async_fetch('https://httpbin.org/ip')
  .then(data => console.log(data))
  .catch(error => console.log('Fetch error: ' + error))
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

请注意,正如您所注意到的,我没有写;分号,这完全没问题,在 JavaScript 中这;不是强制性的,无论您是否写它都没关系,JS 引擎都会检查它并在需要时插入它,只要小心以括号开头的新行(并避免return在不同的行中使用值即可。

带有左右按钮的页脚

HTML

<footer>
  <div>
    <button>Button A</button>
    <button>Button B</Button>
  </div>
  <div>
    <button>Button C</button>
    <button>Button D</button>
  </div>
</footer>
Enter fullscreen mode Exit fullscreen mode

CSS

footer {
  display: flex;
  justify-content: space-between;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

滚动到视图中

我创建了 n 个颜色随机的盒子(div),以便随机选择其中一个并使其在视口中可见。每次重新运行代码时,无论其位置如何,您都会在屏幕上看到所选的盒子。

JS

document.querySelector(`div:nth-child(${random})`).scrollIntoView()
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

展平对象数组

JS

array = alphas.map(a => 
  a.gammas.map(g => g.betas)
).join()
Enter fullscreen mode Exit fullscreen mode

如果您想了解使用forEachwithconcat和 with 的其他不同方法,push请检查此链接(我也使用 jsPerf 做了一些耗时的测试)。

在此处查看 JSFiddle

请记住,如果您想要平坦数组,则可以使用 轻松完成flat()

[1, 2, [3, 4, [5, 6]]].flat(Infinity)
Enter fullscreen mode Exit fullscreen mode

嵌套对象数组

返回一个由n个元素填充内容的数组:
JS

let get_array = (n, content) => Array(n).fill(content)
Enter fullscreen mode Exit fullscreen mode

返回具有 name 属性且具有内容值的对象:

let get_object = (name, content) => 
  Object.defineProperty({}, name, {value: content})
Enter fullscreen mode Exit fullscreen mode

3 层带有对象的数组(嵌套)

a = 
get_array(3, get_object('b', 
  get_array(6, get_object('c', 
    get_array(3, {})
  ))
))
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

没有重复值的数组

JS

const array = [1, 2, 3, 3, 3, 2, 1]
Enter fullscreen mode Exit fullscreen mode

设置策略:

[...new Set(array)]
Enter fullscreen mode Exit fullscreen mode

过滤策略(比较容易理解,但速度较慢):

array.filter((elem, index) => index == array.indexOf(elem))
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

记住,Array.from(iterableObj) = [...iterableObj]

带单位的 HTML 输入

HTML

<span><input type="number" min="0" value="50"></span>
Enter fullscreen mode Exit fullscreen mode

CSS

span {
  background: white;
  border: 1px solid #e8e8e8;
}
input {
  background: inherit;
  outline: none;
  border: none;
  padding: 0 5px;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

响应式背景循环视频

HTML

<video autoplay loop poster="https://website/video.jpg">
  <source src="http://website/video.webm">
</video>
Enter fullscreen mode Exit fullscreen mode

CSS

video.landscape {
  width: 100vw;
  height: auto;
}
video {
  width: auto;
  height: 100vh;
}
Enter fullscreen mode Exit fullscreen mode

请记住,您可以添加任意数量的源以支持不同的视频格式。

在此处查看 JSFiddle

如何打印特定的 HTML 元素

我想要这样的东西:

document.querySelector('div').print() // maybe in the future
Enter fullscreen mode Exit fullscreen mode

在本文发布时,该标准仅支持window.print(),但我们可以使用 CSS 和少量 JavaScript 来实现:

CSS

@media print {
  body.print-element *:not(.print) {
    display: none;
  }
}
Enter fullscreen mode Exit fullscreen mode

JS

function print_this(elem) {
  document.body.classList.add('print-element')
  elem.classList.add('print')
  window.print()
  document.body.classList.remove('print-element')
  elem.classList.remove('print')
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

查看、隐藏、输入和生成密码

喜欢让事情尽可能简单 xD

里面有一个提示input,然后是button显示密码,最后是另一个button生成随机密码。

HTML

<input id="password" type="password" placeholder="type password...">
<button id="view-password"></button>
<button id="generate-password"></button>
Enter fullscreen mode Exit fullscreen mode

查看或隐藏密码:
JS

$view_password.addEventListener('click', e => {
  e.currentTarget.classList.toggle('view')
  if (e.currentTarget.className.includes('view'))
    $password.setAttribute('type', 'text')
  else $password.setAttribute('type', 'password')
})
Enter fullscreen mode Exit fullscreen mode

设置随机密码并确保显示:

$generate_password.addEventListener('click', () => {
  $view_password.classList.add('view')
  $password.setAttribute('type', 'text')
  $password.value = Math.random().toString(36).slice(-8)
})
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

请注意,我个人将选择器的命名const以 $ 开头。

无限选择上一个和下一个

在选择循环中选择每个元素。如果在完成元素列表后立即向前移动,则将从头开始选择;如果反向移动,则同样如此。

HTML

<button id="previous">Previous</button>
<button id="next">Next</button>
<ul>
 <li></li>
 <li class="selected"></li>
 <li></li>
 <li></li>
 <li></li>
</ul>
Enter fullscreen mode Exit fullscreen mode

JS

document.querySelector('#next').addEventListener('click', () => {
  const $selected = document.querySelector('.selected')
  const $next_element = $selected.nextElementSibling
  if (!$next_element)
    $next_element = $selected.parentElement.firstElementChild
  $selected.classList.remove('selected')
  $next_element.classList.add('selected')
})
Enter fullscreen mode Exit fullscreen mode

记住,使用nextElementSiblingand previousElementSibling(DOM 元素)而不是nextSiblingand previousSibling(DOM 对象)。DOM 对象可以是任何东西:注释、独立文本、换行符等等。在我们的例子中,nextSibling如果我们将所有 HTML 元素放在一起,中间不加任何字符,那么效果会很好:

<ul><li></li><li></li></ul>
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

响应式正方形

我见过很多创建响应式正方形的奇葩方法,所以想分享一个简单的方法。点击下方的 JSFiddle 链接,尝试调整结果窗口的大小。

CSS

div {
  width: 60vw;
  height: 60vw;
  margin: 20vh auto;
  background-color: #774C60;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

通过鼠标单击定义的圆形区域

我们将根据点击框区域内的位置来定义圆的面积。我们可以使用 JavaScript 事件、一些基础数学知识和 CSS 来处理这个问题。

宽度和高度是相同的,我们为数学设置哪一个并不重要:
JS

const width = e.currentTarget.clientWidth
Enter fullscreen mode Exit fullscreen mode

鼠标光标距离圆心的绝对位置:

const x = Math.abs(e.clientX  offset.left  width / 2)
const y = Math.abs(e.clientY  offset.top  width / 2)
Enter fullscreen mode Exit fullscreen mode

最大值将告诉我们圆面积的百分比:

percent = Math.round(2 * Math.max(x, y) * 100 / width)
$circle.style.width = percent + '%'
$circle.style.height = percent + '%'
Enter fullscreen mode Exit fullscreen mode

文本覆盖

好吧,也许你想着直接在键盘上启用 Insert 键就行了,但如果没有这个键,或者你想在某些特定的输入框和文本区域输入时始终保持(独立的)覆盖模式,该怎么办呢?其实很简单。

JS

$input.addEventListener('keypress', function(e) {
  const cursor_pos = e.currentTarget.selectionStart
  if (!e.charCode) return

  $input.value = $input.value.slice(0, cursor_pos) + 
  $input.value.slice(cursor_pos + 1)
  e.currentTarget.selectionStart = 
  e.currentTarget.selectionEnd = 
  cursor_pos
})
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

使用闭包重置计数器

设置一个带有闭包和一些外部可访问选项的基本计数器。

JS

const add = (function() {
  let offset = 0
  return function(option) {
    switch (option) {
      case 0: offset = 0; break;
      case 1: offset++; break;
      case 2: offset  ; break;
      default: throw Not a valid option;
    }
    console.log(offset)
  }
})()
Enter fullscreen mode Exit fullscreen mode

请记住,闭包只是让你记录并保护你的变量。

在此处查看 JSFiddle

无限滚动

你见过向下滚动时自动“加载更多”的功能吗?你在 Tumblr 的图片、Gmail 的消息或 Facebook 上看到过吗?很酷,不是吗?无限滚动是分页的替代方案,而且无处不在。它优化了用户体验,根据用户需求(间接地)加载数据。页面、网页和应用的加载速度更快,它只会加载你需要的内容,而不是全部加载。你无需添加额外的交互、按钮或小部件,因为它本身就带有你习惯的正常阅读行为:用鼠标向下滚动,或者用手指在可触摸屏上滚动。

JS

const $ol = document.querySelector('ol')

function load_more() {
  let html = ''

  for (var i = 0; i < 5; i++) html += '<li></li>'
  $ol.innerHTML += html
}

$ol.addEventListener('scroll', function() { 
  if ($ol.scrollHeight  $ol.scrollTop == $ol.clientHeight) 
    load_more()
})
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

请注意,在上面的例子中,我们可以更有效地创建节点和使用appendChild()

材料图标

HTML

<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
 rel="stylesheet">

<i class="material-icons">face</i>
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

使用 box-shadow 的基本 CSS 过渡

当鼠标悬停在元素上时,CSS 会发生变化,并带有缓入缓出过渡效果(缓慢开始和结束)。我们用内阴影(插图)填充元素。

CSS

i { 
  transition: all 0.5s ease-in-out;
  box-shadow: 0 0 0 75px #E94F37 inset;
}
i:hover {
  box-shadow: 0 0 0 4px #E94F37 inset;
  color:#E94F37;
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

将 HTML 表格导出为 CSV 文件

假设您有一个 HTML 表,并且想要将其下载为 CSV 表。

HTML

<table>
  <tr><th>Name</th><th>Age</th><th>Country</th></tr>
  <tr><td>Geronimo</td><td>26</td><td>France</td></tr>
  <tr><td>Natalia</td><td>19</td><td>Spain</td></tr>
  <tr><td>Silvia</td><td>32</td><td>Russia</td></tr>
</table>
Enter fullscreen mode Exit fullscreen mode

首先,您需要从 HTML 转换为 CSV:

JS

let csv = []
let rows = document.querySelectorAll('table tr')

for (var i = 0; i < rows.length; i++) {
  let row = [], cols = rows[i].querySelectorAll('td, th')

  for (var j = 0; j < cols.length; j++) 
    row.push(cols[j].innerText)

  csv.push(row.join(',')) 
} 

download_csv(csv.join('\n'), filename)
Enter fullscreen mode Exit fullscreen mode

之后,您可以使用Blob以下链接下载它:

let csvFile = new Blob([csv], {type: 'text/csv'})

let downloadLink = document.createElement('a')
downloadLink.download = filename
downloadLink.href = window.URL.createObjectURL(csvFile)
downloadLink.style.display = 'none'

document.body.appendChild(downloadLink)

downloadLink.click()
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

键盘事件

用于event.code以人性化的方式了解哪些键被按下。event.key如果您想区分大小写,并避免使用浏览器快捷键,例如:Ctrl + P(打印),请使用此选项。

JS

document.onkeydown = event => {
  switch (event.code) {
    case 'ArrowDown':
      $div.style.top = `${parseInt($div.style.top || 0) + step}px`
      break
    case 'KeyR':
      if (event.altKey) $div.style.top = 0
      break
  }
}
Enter fullscreen mode Exit fullscreen mode

在此处查看 JSFiddle

类似 jQuery 的短选择器

当你必须选择 DOM 元素时,使用 JavaScript 会有点烦人,在这种情况下,我们可能会错过 jQuery,因为原生 JavaScript 实在太长了
。JS

// Select one element (first one)
document.querySelector('#peter')
document.querySelector('.staff')
document.querySelector('.staff').querySelector('.age')
// Select all elements
document.querySelectorAll('.staff')
Enter fullscreen mode Exit fullscreen mode

我们不喜欢在编码时重复事情,如果您在 JavaScript 的开头定义下一个代码,您将能够做到比 jQuery 更好。

function $(selector) {
  return document.querySelector(selector)
}

function $$(selector) {
  return document.querySelectorAll(selector)
}

Element.prototype.$ = function(selector) {
  return this.querySelector(selector)
}

Element.prototype.$$ = function(selector) {
  return this.querySelectorAll(selector)
}
Enter fullscreen mode Exit fullscreen mode

现在你可以把我们的例子写得更短一些:

// Select one element
$('#peter')
$('.staff')
$('.staff').$('.age')
// Select all elements
$$('.staff')
Enter fullscreen mode Exit fullscreen mode

这很容易记住,因为 $ 的行为类似于带有 CSS 选择器的 jQuery,而 $$ 的作用也类似,但它允许你选择多个元素。第一个 $$ 返回找到的第一个元素,第二个 $$ 返回元素列表。

还有一件事,您不能在此代码中使用 jQuery,因为 jQuery 也使用 $,如果您需要它,您必须将代码中的 $ 更改为另一个东西,即:qS。

记住,在 JavaScript 中我们有比类更好的东西:prototype。不管你使用没有class,底层使用的是prototype

属性 (property) 和特性 (attribute) 有何不同?

属性 (property) 位于 DOM 中;属性 (attribute) 位于解析到 DOM 中的 HTML 中。

HTML

<body onload="foo()">
Enter fullscreen mode Exit fullscreen mode

JS

document.body.onload = foo
Enter fullscreen mode Exit fullscreen mode

当不需要逻辑时,避免使用 switch 语句

数组更快,在下一个例子中,如果您想知道现在是第九个月,您只需编写代码即可months[9]

JS

const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
Enter fullscreen mode Exit fullscreen mode

极客的东西

★ 你和我一样热爱 HTML、CSS 和 JavaScript 吗?^^ 别忘了看看我关于 Web 开发的极客穿搭;P

文章来源:https://dev.to/gengns/short-tricks-of-html-css-and-javascript-582g
PREV
There's no "else if" in JS Grammar is not a joke...
NEXT
8 个技巧助你打造下一份技术简历