现代 Web 开发 - UI - HTML & CSS
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
当我还在努力消化2021年关于构建Web用户界面的所有复习资料时,我在DEV上看到了这个“我设计,你构建”的挑战:
喜悦之情油然而生。挑战接受!但这次有点不一样——我将使用相同的设计,并尝试所有我想探索的不同技术,多次构建网站:
- HTML 和 CSS
- CSS-in-JS(可能是 React 和 styled-components)
- Tailwind CSS
- 组件库(可能是 Chakra UI)
在本系列博客的开头,我原本打算只写一篇关于用户界面(UI)的文章,比较一下所有这些技术。但写完HTML和CSS部分后,我发现它们都需要单独写一篇博客。我会像第一篇文章一样,在所有文章前加上“UI -”的前缀。
HTML 和 CSS 还停留在 2009 年的水平
不,并非如此。现在浏览器对 Flex 和 Grid 布局的支持非常好——不用它们岂不是太可惜了?等等,要怎么用它们来构建完全响应式的页面来着?顺便问一下,移动优先现在还适用吗?为了缓解这些问题带来的突如其来的焦虑,我从头到尾读了一遍这篇文章:
https://www.smashingmagazine.com/2018/02/media-queries-responsive-design-2018/
行得通。我的意思是,最好的办法当然是听作者的演讲录音,但网上似乎还没有这样的录音,所以这篇文章也行。
好的,那么:
- Flexbox 和 Grid 是现代响应式网页设计的核心。
- 移动优先仍然适用,但断点应该设置在设计在视觉上出现问题的地方,而不是实际的设备宽度。
以下是我用来复习 CSS Grid 相关知识的视频:
每个人的学习方式都不同,但我记得我把那个视频的播放速度调到 1.5 倍,它就足以吸引我看完。之后,当你在使用 Grid 构建东西时遇到具体问题(你肯定会遇到),gridbyexample.com就能为你提供答案。
至于 Flexbox,我已经记不清我是从哪些不同的地方学来的了,但如果你觉得这些内容难以理解,那可能意味着你应该去查阅一下网上众多关于 Flexbox 的优秀资源:
既然我们聊到了这篇博客的先决条件部分,你知道还有什么也是必读的吗?无障碍设计。没错,我知道你打算以后再学习无障碍设计……说实话,我也不能完全怪你——把让网页浏览器与辅助技术正确兼容的责任完全推给开发者,感觉就像是用纸吸管来对抗气候变化一样。不过,这两种看似荒谬的情况都包含着一丝真理:就像应对气候变化很可能需要改变消费者的行为一样,在找到更好的解决方案来解决技术无障碍问题之前,目前形式的无障碍设计(例如 WAI-ARIA)仍然是必要的。
从哪里开始呢?就从这段精彩的介绍开始吧:
接下来是这个实用建议:
在开始挑战之前,我最后推荐一篇阅读材料。不过,这篇读起来最有趣——它是一篇关于 CSS 动画基础知识的交互式指南:
https://www.joshwcomeau.com/animation/css-transitions/
好了,现在我们已经掌握了响应式网页设计(包括弹性布局和网格布局)、无障碍设计和动画方面的知识,准备马上开始:
开始挑战
我重点介绍了桌面设计中的三个重要组成部分:顶部导航栏、产品列表组件(您可以筛选的项目网格)以及展示/滑块/轮播图。
我们将在本系列的后续文章中介绍 UI 组件库,但现在我们必须先通过案例研究来了解它们。
窃取代码借鉴最佳实践。像我们设计中使用的这三个 UI 组件一样,UI 组件是非常常见的模式,在各种网站和应用程序中反复出现。因此,了解其他人是如何做的是很有意义的。
十年前,这意味着要阅读某位杰出设计师(没错,这位杰出设计师是位男性)在其个人博客上发表的文章。而如今,一个不错的起点是了解最流行的设计系统/组件库。当然,你仍然应该广泛阅读、收听播客,以及获取各种你喜欢的内容,但作为当前最佳实践的集大成者(通常如此——我无意在此引发任何争论),流行的组件库是一个很好的切入点。
Material Design是谷歌对这个主题的最佳诠释。Chakra UI是一个真正意义上的协作项目,在开源社区的密切关注下构建而成。Bootstrap曾一度风靡全球,如今却因过度流行而略显疲态,但其目前的第五版融合了最佳实践和丰富的实践经验,堪称宝贵的资源。我们将研究这些库以及其他许多资源,以深入了解我们所确定的三个组成部分。
基础样式
我已经将每个组件拆分到各自的 Git 分支中,这样你就可以单独检查它们,而不会被无关的代码干扰。主分支则包含了所有组件。
代码
如果其他部分分别是组件一、二和三,那么这部分就像是组件零?在编写页面基础样式以及我没有用红圈圈出的两个简单部分时,我们还需要考虑一些其他因素,这些因素在前面的前提条件部分没有提到。不过,这些主题很容易让人陷入无尽的讨论,所以我尽量言简意赅,不提供任何“延伸阅读”链接。
CSS 单元和(响应式)排版
em现在,除了边框宽度或您明确不想改变某些元素之外,所有以前使用像素的地方都可以使用 s。它们与浏览器设置中的自定义字体大小配合使用效果很好;使内边距的设置更加便捷,并且通常只需关注font-size元素的大小,间距就会自动调整。- 手动设置
font-size不同断点下的字体大小,使其在该尺寸下看起来美观。我们将设置三个主要断点:小(小于 100 像素)48em、中(大于80em100 像素)和大(80em大于 100 像素)。“中”和“大”断点基本沿用桌面端的设计,但字体大小和间距会进行调整。
响应式图像
对于内容丰富的大型网站来说,手动进行美术指导并处理不同分辨率的图片几乎是不可能的。您肯定需要借助像 Cloudinary 这样的图片服务。
在我们的概念验证中,我导出了两种尺寸的大图(例如主图),并使用 `color` 和 `color` 函数srcset来选择最合适的尺寸。我没有单独导出裁剪后的移动版图片,而是通过`color` 和 `color` 函数sizes实现了裁剪效果。object-fitobject-position
其他
- 几乎完美。我没有特意追求像素级的完美,但除了设计允许更大灵活性的部分外,大部分尺寸和间距都与设计稿相同。
- 仅支持现代浏览器。即便如此,由于这是纯 HTML 和 CSS,完全没有构建步骤,我甚至没有添加通常会由 autoprefixer 等工具添加的浏览器前缀。
主导航栏
这可能是网站上最普遍的用户界面元素。它几乎一直存在于所有网站中,并随着时间的推移而不断演变:从第一个网站dl中的链接,到90 年代开始并延续至今的带有内边距、左右浮动的水平布局,再到 Web 2.0 时代流行的鼠标悬停下拉菜单,以及尽管有人反对,汉堡菜单仍然广泛普及。ulli
在上述流行的组件库中,Material Design 的顶部应用栏虽然更侧重于应用而非网站,但仍然是一个很好的概览。该页面上的第一个相关链接也值得一读,它能引导你从 UI/UX 的角度思考问题,而不仅仅是将设计稿转换成网页。就实现而言,Bootstrap 的导航栏似乎更符合我们的需求。
说到这里,我们的导航组件到底需要具备哪些功能呢?我们同时提供了桌面版和移动版的设计,这很好:
现在,我让你们读了那么多文章可不是白读的,所以让我们运用所学知识来完整地定义我们的导航组件吧:
- 对于移动版来说,点击菜单切换图标后滑入的全屏侧边栏元素似乎是最合适的解决方案。它与整体设计风格相得益彰,而且尺寸足够大,可以容纳家具店网站上通常会有的所有产品目录链接。
- 搜索和购物车按钮非常重要,不应该被隐藏在汉堡菜单后面,所以我们也可以将它们保留在移动设备上的相同位置,并将切换图标移到左侧。
代码
观察结果:
- 我认为能够
display: block;在移动设备上使用默认设置,display: flex;在桌面设备上使用响应式菜单,这种方式非常简洁美观。另外,我没有ul > li对菜单项进行任何处理,这也没关系。当然,你也可以添加,那样也完全没问题。 - 你会注意到我并没有过度使用 aria 属性。只为一些重要的图标按钮(例如搜索等)添加了一些角色和标签。
- 在可访问性方面,我特别注意确保不会破坏之前运行正常的功能,例如使用键盘导航页面。而当你把
translate菜单移出屏幕时,恰恰会破坏这些功能。如果你现在按 Tab 键从 logo 移动到搜索按钮,焦点似乎会暂时消失,因为它会穿过菜单项(这些菜单项在屏幕上不可见)。这就是 CSS 的作用visibility: hidden(同时也是为了防止屏幕阅读器读取到菜单项)。对于更复杂的组件,你可能需要tabindex用 JavaScript 来管理元素的可见性才能解决这个问题,但在这个例子中,只需要使用 CSS 的 visibility 属性,并确保它与我们的动画兼容即可。 - 我从这个挑战的优秀解决方案中借鉴了汉堡图标的动画效果。不过,我当时肯定是在拖延其他事情,因为我没有像正常人那样直接复制 SVG 动画,而是用 CSS 重写了一遍。
- 我以前从没想过自己会需要自定义过渡时间函数,但现在看来确实需要。
cubic-bezier你看到.search的transition属性是来自这里的“easeOutQuart” 。它的反向函数“easeInQuart”用于完善搜索框缓慢出现(在背景模糊生效后)并在你关闭它后迅速消失的效果。
展示/轮播/轮播图
啊,轮播图——网页设计师最讨厌的组件。这大概就是为什么你在大多数流行的组件库里都找不到它的原因(好吧,Bootstrap 仍然保留了一个,但这大概也是 Bootstrap 不再那么流行的原因之一)。不过,轮播图短期内不会消失。尤其是在移动端,滑动操作已经成为一种本能。Airbnb 的首页和 App 上的滚动功能如今已成为经典。那么,我们该如何实现滑动浏览呢?
您可能在组件库中找不到轮播组件,但您知道在哪里可以找到吗?在WAI-ARIA 创作实践中。
不过,我采用了一种更简单的方法。首先是代码:
代码
正如我所说,我采取了一种更简单的方法。这并非因为我标新立异,而是因为我发现了CSS 滚动捕捉!我的天哪!这是真的吗?这怎么可能?
你添加了两个 CSS 属性,然后……就……生效了?这在网页上根本不可能发生。谁允许的?他们难道没考虑到这会引发一系列问题吗?
好吧,说真的,这太棒了,但我们还是继续吧。
有了滚动捕捉功能,我们的轮播图就完全不需要是轮播图了。所有“幻灯片”内容都会始终存在,只需滚动即可查看。对于屏幕阅读器来说,这和页面上的普通内容没什么区别(我给幻灯片添加了一个标签role="group",但即使没有,屏幕阅读器也能按顺序正确朗读内容)。
对于键盘导航,当展示页面获得焦点时,按左右箭头键通常只会使内容水平滚动一小段距离。得益于自动滚动功能,这小段滚动会变成完整滚动到上一张/下一张幻灯片。scroll-behavior: smooth;这也能确保在使用 Tab 键切换幻灯片时发生同样的情况(Firefox 浏览器似乎除外,但如果需要,可以用一些 JavaScript 代码轻松修复)。
按钮的 JavaScript 代码也变得非常简单:next/previousElement.scrollIntoView()它IntersectionObserver会跟踪当前幻灯片,以便根据需要有条件地禁用上一页和下一页按钮。
(可筛选)产品列表组件
你有没有看过前段时间在网上疯传的“10分钟、1分钟、10秒内画蜘蛛侠挑战”?
我们页面的10秒钟版本就只有产品列表组件。这是网站的主要功能,也是访客访问的原因。我刚开始接触网页开发时就学会了识别这种最基本的模式。我最初使用的是WordPress——它提供了一个index.php模板,可以用来设计列出所有博客/商品的页面,以及single.php用户点击其中一个商品后显示的单独视图。这种模式以不同的形式无处不在:YouTube、Twitter、新闻网站、你的作品集等等。看到一堆东西,点击其中一个。
由于产品列表通常是网站/应用的核心功能,与业务逻辑紧密相关,因此组件库中通常不会提供通用的“产品列表”组件。取而代之的是,你会找到一些实用的小工具,帮助你自行构建这项核心功能。例如,Material Design提供了卡片组件,Chakra 提供了美观的链接叠加层。Bootstrap 也提供了卡片、列表分组、分页等组件。
分页功能很有意思,因为它属于我上面提到的“变体”之一——它是商品列表组件的一个属性。从这个意义上讲,筛选也是该组件的一个属性。当然,这是一个重要的属性,因为它从根本上改变了用户与组件的交互方式,但它仍然只是一个属性,是组件“拥有”的东西。我想说的是,不要首先把这个组件看作是一个筛选组件,而应该把它看作是一个带有筛选功能的产品列表组件。这将为我们思考如何实现它奠定基础。现在就开始吧。
- 桌面布局完全采用了 CSS Grid 布局:三列,行数根据需要而定。移动布局支持水平滚动。我也实现了快速滚动(或者说“快速滚动”?),但这属于用户体验设计范畴,需要仔细考虑。关键在于减少惯性。用户在使用滚动捕捉功能时,浏览产品页面是否更容易?
- 经典的砌体动画效果是实现过滤动画效果时首先想到的。它不仅能单独表现出现/消失的元素,还能让周围元素移动,从而完美地展现过滤过程。但我认为它并不适合我们的情况,原因有以下几点:
- 在这个概念验证中,我们可以始终在 HTML 中显示所有产品,并使用 CSS 隐藏需要过滤掉的产品。但在实际部署这个电商网站时,你需要从后端获取产品信息。加载动画之后的所有操作都会造成用户体验的割裂感。
- 用 CSS Grid 实现元素位置动画似乎相当复杂。因为我是在考虑了上述第一个原因之后才做出决定的,所以没有深入研究这个问题,但我还是把它列在这里供大家参考。这并非出于偷懒,而是为了考虑到预算和时间限制。正如上文所述,这是我们网站的核心功能,所以如果您认为瀑布流式布局效果非常重要,那么就应该提前规划并实现相应的解决方案。这个解决方案可以是任何形式,从研究可以实现 CSS Grid 动画的库,到完全切换到绝对定位。我想表达的观点是……实际上有两点:1)确定哪些功能重要以及您愿意投入多少时间;2)当您看到某些实现方式与您的想法不同时,请考虑他们这样做很可能是有原因的——如果合适,可以询问他们原因。
代码
笔记:
- 为了实现动画效果,我最终采用了淡入淡出的方式。这样看起来足够自然,也与整体设计和其他动画风格保持一致。JavaScript 代码可能看起来有点复杂,但这没办法,因为经典的动画问题——无法直接从一个元素过渡
display: block;到另一个元素——必须如此display: none;。- 为了实现加载效果,我只会淡入淡出元素内部的内容
.product,并无限循环地改变背景颜色以指示加载中。我可能会在接下来的博客文章中实现这一点。
- 为了实现加载效果,我只会淡入淡出元素内部的内容
- 使用单选按钮组作为筛选按钮可以解决我们通常会遇到的大部分辅助功能问题。键盘导航?没问题。标签聚焦
:focus-visible?没问题。产品列表本身就是一个列表ul,会aria-live="polite"在内容更改时通知屏幕阅读器。
废话不多说(哈哈,好像我还能再拖延下去似的),以下是完整的挑战演示和代码:
结论
我也会尝试用列表的形式来写。以下是我在2021年末使用HTML和CSS构建网站的一些心得体会:
- 浏览器万岁!!!你根本想象不到以前有多糟糕。用移民法的话来说,我们的工作应该算是“高技能劳动”。嗯,很长一段时间里,网页开发人员99%的高技能都体现在了解和解决浏览器兼容性问题上。我虽然不会打领带,但Internet Explorer 6的XMLHttpRequest不是原生JavaScript对象而是ActiveX对象这件事,至今还深深地印在我的脑海里。
- 这仍然是一份全职工作。我们在这里只是浅尝辄止地探讨了无障碍设计,甚至还没涉及到性能优化。任何谈论全栈的人,要么是偶然发现了一位罕见的十倍速编码高手(而且薪水偏低),要么更有可能的是,他们忽略了刚才提到的许多专业领域。(我并不反对职责会不时变化的全栈角色;这里只是针对我提到的特定情况。)
- 孩子们都很好。我不想重提过去几年(其实差不多十年了)关于工具和过度设计的争论。我只是想表达一下我的看法:即使是在2021年搭建一个简单的网站,“直接打开记事本写代码”这种想法也感觉非常局限,而且并没有带来多少实际好处。
好的,那么在下一篇博客中,我们将使用 React 和一些 CSS-in-JS 库(例如 styled-components)来重建这个页面。欢迎在Twitter上关注我。我几乎从不发推文,但如果有人从这里关注我,我会破例在下一篇文章发布时发推文通知他们。
文章来源:https://dev.to/microbouji/ui-html-css-5k2

