在今天的例子中,我想重构一段 HTML,具体来说,就是网站的标题菜单。我删除了重复的元素和不相关的属性以保持示例干净。
免责声明。我从真实来源(网站、开源项目、文章)中提取重构示例,更改实体或其他独特组件的名称。我不知道也不可能知道代码编写时的上下文、条件或时间,因此我所有的修复都是我个人对代码中可以更改的内容的主观看法。因此,我的修复不会对代码源或其创建者进行任何负面评估。
来源
<DIV类= “NAV-链接”> <DIV类= “UITabs -with-图标”> <a类="UITabs-tab" HREF ="/map" data-tab ="map"> <DIV类=” UITabs-content"> <div class ="UITabs-icon"> <svg class ="ico" width ="20" height ="20" viewBox ="0 0 20 20" fill ="#9e9e9e" xmlns ="http ://www.w3.org/2000/svg" > <路径填充规则=“evenodd”剪辑规则=“evenodd”d ="..."> </path> </svg> </div> 地图 </div> </a> <a class ="UITabs-tab" href ="/discount" data-tab ="discount"> <div class ="UITabs-content"> <div class ="UITabs-icon"> <svg class ="ico"宽度="20"高度="20" viewBox ="0 0 20 20"填充="#9e9e9e" xmlns ="http://www.w3.org/2000/svg" > <path fill-rule ="evenodd “剪辑规则=“evenodd”d ="..."> </path> </svg> </div> 折扣 </div> </a> <div class ="UITabs-tab" data-tab ="search"> <div class ="UITabs-content"> <div class ="UITabs-icon"> <svg class ="ico" fill ="#9e9e9e" height ="24" viewBox ="0 0 24 24" width ="24" xmlns ="http://www.w3.org/2000/svg" > <path d ="..."></path> <路径d ="M0 0h24v24H0z"fill ="none"></path> </svg> </div> 搜索 </div> </div> <div class="UITabs-indicator" style="transform..."></div> </div> </div>
我注意到的第一件事是过度使用<div>
标签。当然,这个标签没有任何问题,因此,像所有好东西一样,它被使用得太频繁了。
接下来是嵌套深度,它显然不带有任何语义含义。此外,深度嵌套会增加 HTML 文件的大小,减慢 CSS 解析速度,并降低可读性。
此外—— 图标是在 HTML 中定义的。这也不是关键,此外,它取决于缓存策略、CDN 的存在、支持的浏览器列表等。在这种情况下,图标不会与 HTML 文件分开加载,这意味着它们将立即可见,没有内容跳转,但它们也会增加文件大小,这会减慢其加载和解析速度。显然,这件事没有明确正确或错误的决定,但从语义的角度来看,在我看来,图标堵塞了代码。此外,与图片不同,图标仅从视觉的角度来看才是重要的。因此,最好在 CSS 中定义页面的视觉部分。
让我们找到其他语义正确的标签,减少嵌套深度,并清除这些代码中不必要的元素。让我们一步一步来。
容器
由于这是一个菜单,<nav>
用于导航元素的标签更适合于容器。
现在的问题是——为什么我们需要两个<div>
相互嵌套的标签?显然,同时.nav-links
包含相对于其父级的定位样式,.UITabs
才是导航的真正父级。我认为将样式拆分为两个不同的标签毫无意义,因此我建议将它们替换为一个<nav>
带有两个类的标签。
<nav class="UITabs -with-icons nav-links"> <a .../> <a .../> <div .../> <div .../> </nav>
菜单项
我对链接标签没有任何疑问,但还有额外的嵌套,.UITabs-content
类。同样,这是基于样式的标签分离,但在这种情况下,最有可能的是尝试遵循一种方法,例如BEM,但我认为没有理由将.UITabs-tab
块的样式与其唯一的直接分开孩子.UITabs-content
。此外,两个类都设置了填充,相互覆盖。在容器的情况下,我建议将这两个标签合二为一。
<a class ="UITabs-tab" href ="/map" data-tab ="map">
<div class ="UITabs-icon">...</div>
地图
</a>
有一个<div>
带有链接的菜单项,这在语义上是不正确的,因为根据定义,菜单项是用户交互的元素,这意味着它必须是链接或按钮。在我们的例子中,这是搜索按钮,所以让我们把它写下来。
<button class ="UITabs-tab" data-tab ="search">
<div class ="UITabs-icon">...</div>
搜索
</button>
图标
正如我上面已经写的,我建议从 HTML 中删除图标,它们的位置在 CSS 中,并且由于我不想在 HTML 中使用任何额外的元素,它们将被定义在一个伪元素中。
<style> .UITabs-tab.-map-icon::before { content: url(/map-icon.svg); //第一个选项 } .UITabs-tab.-discount-icon::before { content: url( data:image/svg+xml; utf8, <svg>...</svg> ); //第二个 } ... </style><a class ="UITabs-tab -map-icon" href ="/map" data-tab ="map"> 地图 </a>
其他元素
引出问题的还有最后一点—— .UITabs-indicator
。基本上,这是活动菜单项的下划线,使用 javascript 设置样式。我认为这是开销,因为使用 CSSborder
属性很容易实现下划线。或者,如果它看起来比 bar 更复杂,您可以使用::after
伪元素或box-shadow
属性进行样式设置。
<style>
.UITabs-tab.active {
border-bottom: 4px solid currentColor;
}
</style>
结果
<style> .UITabs-tab.-map-icon::before { content: url(/map-icon.svg); } .UITabs-tab.-discount-icon::before { content: url( data:image/svg+xml; utf8, <svg>...</svg> ); } .UITabs-tab.-search-icon::before { content: url( data:image/svg+xml; utf8, <svg>...</svg> ); } .UITabs-tab.active { border-bottom: 3px solid currentColor; } ... </style><nav class="UITabs -with-icons nav-links"> <a class ="UITabs-tab -map-icon" href ="/map" data-tab ="map"> 地图 </a> <a class ="UITabs-tab -discount-icon" href ="/discount" data-tab ="discount"> 折扣 </a> <button class ="UITabs-tab -search-icon" data-tab ="search"> 搜索 </button> </nav>
在我看来,这个 HTML 更具可读性和语义正确性。顺便说一句,我从来没有使用过<div>
,虽然没有这样的目标,但是,如果你坚持语义,它就会经常发生