大数跨境

“老式” CSS 的案例

“老式” CSS 的案例 索引目录
2025-04-02
0
导读:现在人们还在 CSS 文件中编写 CSS 吗?说实话,我现在不像刚开始工作时那样紧跟潮流。

现在人们还在 CSS 文件中编写 CSS 吗?说实话,我现在不像刚开始工作时那样紧跟潮流。部分原因是我开始觉得,与我刚开始工作时相比,现在的在线 Web 开发社区已经变得更加“我的方式是最好的方式”,而那时正是 HTML 表格时代的末期和浮动时代的开始。

我很喜欢这张幻灯片,它出自 2024 年 Web Directions Code 上的“CSS 现状”演讲


无论如何,抛开个人观点,我确实有一些涉及 CSS 文件中的 CSS 的项目。这是一个 Drupal 10 网站,因此自定义主题使用 CSS。你可能会问,2025 年谁还会使用 Drupal?显然,在我们所知的所有内容管理系统的网站中,有 1.2% 使用 Drupal。这占所有网站的 0.9%。截至撰写本文时,估计有 1.92 亿个积极维护的网站,所以这仍然是一个不错的数字。

那么用例是什么?

用例是 i18n。如果您是 Drupal 新手,或者像我一样从 Drupal 7 的长期中断中回归,如果您直接谷歌搜索,Drupal 文档 SEO 会有点混乱。很大程度上是因为 Drupal 7 的保质期很长。

无论如何,最新的 Drupal i18n 文档位于第 10 章。使您的网站支持多种语言多语言指南。如果您想在自己的 Drupal 10 网站上实现 i18n,请转到那里。

我试图解决的具体问题与语言切换器有关。在 Drupal 网站上启用多语言功能后,就会出现一个语言切换器块,您可以将其放置在您认为合适的位置。



我想,根据您使用的 Drupal 主题,可能会或可能不会有一些与块相关的样式。但由于我的网站是完全自定义实现的,所以我的主题是基于Starterkit 主题构建的。

无需对默认实现进行任何操作,一旦您在原始主题的标题区域中打开语言切换器块,您将获得您的网站支持的所有语言的无序列表。



这些语言标签可以通过管理界面进行编辑。您必须转到admin/config/region/language并编辑其中列出的每种语言。我的用例只涉及 2 种语言,因此我决定将语言切换器设计为标题上的附加链接选项,标签为 2 个字母的语言代码。

使用 Twig 进行模板

如果没有 CSS 类,您就无法使用老式 CSS。而在 Drupal 主题领域,这意味着现在是Twig模板时代。Drupal 中的模板利用命名约定让您覆盖它们。

因此,如果您从头开始使用 starterkit 基础主题,您的现成标记将被包裹在层层<div>s 中,我个人并不喜欢这种情况。我要做的第一件事是使用提供一些有用的 CSS 类名的模板覆盖page.html.twigregion.html.twig模板。

# page.html.twig
{% if logged_in %}
{{ page.admin }}
{% endif %}

<header class="site-header" role="banner">
{{ page.header }}
</header>

<main role="main">
<a id="main-content" tabindex="-1"></a>
<h1 class="visually-hidden">{{ current_page_title }}</h1>
{{ page.content }}
</main>
# region.html.twig
{%
set classes = [
'region',
'region-' ~ region|clean_class,
]
%}
{% if content %}
<div{{ attributes.addClass(classes) }}>
{{ content }}
</div>
{% endif %}

现成的菜单列表也没有 CSS 类。不,还得为菜单添加一些。

# menu--main.html.twig
{% import _self as menus %}

{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
{% import _self as menus %}
{% if items %}
{% if menu_level == 0 %}
<ul{{ attributes}} class="site-nav__links menu--level-{{ menu_level + 1 }}" id="siteNavMenu">
{% else %}
<ul class="menu--level-{{ menu_level + 1 }}">
{% endif %}
{% for item in items %}
{%
set classes = [
'menu-item',
item.is_expanded ? 'has-submenu',
'menu-item--level-' ~ (menu_level + 1)
]
%}
<li{{ item.attributes.addClass(classes) }}>
{{ link(item.title, item.url) }}
{% if item.below %}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}

最后,我想在导航块上添加一些额外的东西,比如网站徽标和移动菜单图标,这意味着覆盖主菜单块。

# block--blank-main-menu.html.twig
{% set heading_id = attributes.id ~ '-menu'|clean_id %}

<nav class="site-nav" role="navigation" aria-labelledby="{{ heading_id }}"{{ attributes|without('role', 'aria-labelledby') }}>
{% if not configuration.label_display %}
{% set title_attributes = title_attributes.addClass('visually-hidden') %}
{% endif %}
{{ title_prefix }}
<h2{{ title_attributes.setAttribute('id', heading_id) }}>{{ configuration.label }}</h2>
{{ title_suffix }}

<a href="{{ path('<front>') }}" rel="home" class="site-logo">
<img src="{{ site_logo }}" alt="{{ 'Home'|t }}" fetchpriority="high" />
</a>

<div class="site-links-wrapper" data-nav-wrapper id="siteNavLinks">
{{ content }}
</div>

<button
type="button"
class="site-nav__toggle"
aria-controls="siteNavMenu"
aria-label="Toggle Menu"
title="Toggle Menu"
id="siteNavToggle"
>
<div id="menuIcon" class="menu-icon">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</button>
</nav>

drush cr在摆弄模板之后,一定要记住这一点。

CSS 时间

之后就全是 CSS 了。主要是使用 flexbox。但让我们看看(几乎)逐行浏览它对不再编写“传统”CSS 的人来说是否有意义,无论这意味着什么。

我希望我的标题在用户向下滚动时仍能固定在页面顶部。这里的诀窍是记住设置top值,否则它不会粘在顶部。

.site-header {
padding: 0 var(--space-m);
position: sticky;
top: 0;
z-index: 2;
box-shadow: var(--box-shadow);
background-color: white;
}

我有一个<nav>带有 CSS 类的元素.site-nav,它环绕着网站徽标、导航链接列表和移动菜单切换按钮。让我们将其设为弹性框,并使里面的所有内容居中对齐,再加上一些基本的悬停样式。

.site-nav {
display: flex;
align-items: center;
}

.site-logo {
flex: none;
}

.site-nav__links {
list-style: none;
padding-inline-start: 0;
}

.site-nav__links a {
display: block;
color: currentColor;
transition: text-decoration 200ms ease-in-out;
white-space: nowrap;
text-underline-offset: 8px;
text-decoration: underline 1.5px transparent;
padding: var(--space-s) var(--space-2xs);
}

.site-nav__links a:hover {
background-color: ghostwhite;
}

.site-nav__links .is-active {
text-decoration-color: currentColor;
}

至于语言切换器,默认情况下它是一个无序列表,但我们可以而且应该稍微修饰一下。

.language-switcher-language-url {
flex: none;
}

.language-switcher-language-url .links {
display: flex;
list-style: none;
padding: 0;
margin-inline-start: var(--space-2xs);
}

.language-switcher-language-url .links li:first-child::after {
display: inline-flex;
content: "|";
}

.language-switcher-language-url .links a {
padding: var(--space-s) var(--space-2xs);
}

此时,您的标题看起来仍然很不正常。别担心,这都是过程的一部分。



当视口中有足够的空间时,对于此示例,当至少有 700px 的空间时,每个人都可以在同一线上闲逛。

@media screen and (min-width: 700px) {
.region-header {
display: flex;
align-items: center;
}

.site-links-wrapper {
flex: 1;
}

.site-nav {
flex: 1;
}

.site-nav__links {
display: flex;
justify-content: center;
}

.site-nav__toggle {
display: none;
}
}

这些布局样式本质上确保链接列表占据了网站徽标和语言切换器之后剩余的所有空间



无需进一步修改标记,我们可以添加一些 JavaScript 来帮助创建移动菜单。但首先,要进行样式设置。

@media screen and (max-width: 699px) {
.site-links-wrapper {
position: absolute;
background-color: white;
top: var(--site-header-height);
right: 0;
transition: transform 300ms ease-in-out;
border-block-start: 1px solid lightgrey;
}

.site-links-wrapper.offscreen {
transform: translateX(100%);
}

.site-links-wrapper a {
padding-inline: var(--space-s);
}

.language-switcher-language-url {
position: absolute;
top: 25px;
right: calc(var(--space-m) + var(--space-xs) + 24px);
}
}

这会将链接列表绝对定位到网站标题下方,并固定在视口右侧。如果您想知道为什么语言切换器也是绝对定位的,这是因为标记的结构方式。

如上所述,语言切换器是 Drupal 系统块。我们可以重写主菜单模板以包含语言切换器吗?可能,但在重写和使用 CSS 之间,我选择了 CSS 路线。

因此,我们采取的方法是将语言切换器放在移动菜单切换按钮旁边。我认为这是两害相权取其轻的方法。

移动菜单切换的样式大致如下,本质上只有 3 条黑线,当open将类添加到图标时,它们应该会变成一个十字。

.site-nav__toggle {
border: 0;
background: initial;
padding: var(--space-xs) 0;
color: currentColor;
margin-inline-start: auto;
}

.menu-icon {
position: relative;
transform: rotate(0deg);
transition: 0.5s ease-in-out;
cursor: pointer;
height: 1em;
width: 1.5em;
}

.menu-icon span {
display: block;
position: absolute;
height: 4px;
width: 100%;
background: currentColor;
border-radius: 4px;
opacity: 1;
left: 0;
transform: rotate(0deg);
transition: 0.25s ease-in-out;
}

.menu-icon span:nth-child(1) {
top: 0;
}

.menu-icon span:nth-child(2),
.menu-icon span:nth-child(3) {
top: 50%;
}

.menu-icon span:nth-child(4) {
top: 100%;
}

.menu-icon.open span:nth-child(1),
.menu-icon.open span:nth-child(4) {
top: 50%;
width: 0%;
left: 50%;
}

.menu-icon.open span:nth-child(2) {
transform: rotate(45deg);
}

.menu-icon.open span:nth-child(3) {
transform: rotate(-45deg);
}

少量 JavaScript

移动菜单的实际打开和关闭需要一些 JavaScript 的帮助。

// Site navigation CSS classes
const siteLinksWrapper = document.querySelector("[data-nav-wrapper]");
const wideNavMinWidth = window.matchMedia("(min-width: 700px)");
handleNavDisplayStyles(wideNavMinWidth);
wideNavMinWidth.addEventListener("change", handleNavDisplayStyles);

const siteNavToggle = document.getElementById("siteNavToggle");
const siteNavLinks = document.getElementById("siteNavLinks");
const menuIcon = document.getElementById("menuIcon");

if (document.contains(siteNavToggle)) {
siteNavToggle.addEventListener("click", handleMobileNavToggle, false);
}

function handleMobileNavToggle(event) {
siteLinksWrapper.classList.toggle("offscreen");
if (siteLinksWrapper.getAttribute("class").includes("offscreen")) {
menuIcon.classList.remove("open");
} else {
menuIcon.classList.add("open");
}
}

function handleNavDisplayStyles(event) {
if (event.matches) {
siteLinksWrapper.classList.remove("offscreen");
} else {
if (siteLinksWrapper) {
flashPrevention(siteLinksWrapper);
}
siteLinksWrapper.classList.add("offscreen");
}
}

function flashPrevention(element) {
element.setAttribute("style", "display:none");
setTimeout(() => {
element.removeAttribute("style");
}, 10);
}

完成所有这些之后,你最终会得到如下结果:

总结

说实话,写这篇文章真的很有趣,尤其是我重新构建 Drupal 安装以确保所有主题代码不会被我生产网站上的其他组件污染的部分。如果有人还在使用 Drupal,或者还在写“老式”CSS,请告诉我。我感觉和你们所有人都有一种遥远的亲切感。



【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444