在CSS中是否有一个选择器,可以匹配URL中特定的值?

19

有没有一种选择器只在匹配特定的URL或URL的一部分时应用CSS?

例如,这是我的CSS样式表:

p {
   color: green;
}

url("home.html") {
   color: blue;
}

url("about.html") {
   color: yellow;
}

path("/path/index*") {
   color: indigo;
}
当用户访问home.html时,我希望应用home.html选择器。当我在about.html URL上时,我希望应用about.html选择器。 CSS媒体查询允许您在视图宽度更改时切换到不同的样式集。它还允许您在用户要在屏幕上查看或将其发送到打印机时指定不同的样式集。 我的问题是,“是否可以根据URL或URL中的值指定不同的样式集。”因此,这不是关于如何做我所问的事情,而是关于是否可能做到。 我正在使用CMS,它有一个主题,允许您添加自己的CSS。有一个样式表。就这些。不是两个而是一个。 我有一个页面只有特定的CSS,而只有该页面。这就是我的问题的起源。可能会有成千上万种解决方法,但我的问题不是关于解决方法。 但是,既然已经回答了这个问题,我不介意与问题相关的解决方法。
6个回答

15

看起来 @document 规则是专门针对这种情况提出的,但它已从CSS3规范中删除并计划用于CSS4。根据我的测试,它似乎不被支持,并且在此发布时未在caniuse中列出。

语法如下:

@document url("http://www.example.com/widgets/") {
  body {
    color: white;
    background: tomato;
  }
}
/* The above applies styles only to the page at the given URL  */

@document url-prefix("http://www.example.com/widgets/") {
  /* 
  Styles written here are applied to all URLs that 
  begin with 'http://www.example.com/widgets/'  
  */
}

@document regexp("https:.*") {
  /* Styles written here are applied to all URLs that begin with 'https:' */
}

@media查询测试代码以便比较:

var styleTag = document.createElement ("style");
document.head.appendChild (styleTag);
var sheet = styleTag.sheet;
sheet.insertRule ("@media (min-width:600px) { html {color:red}}", 0);
console.log(document.styleSheets.length);

结果:

// no errors, stylesheet is added

测试代码测试 @document 规则:

var styleTag = document.createElement ("style");
document.head.appendChild (styleTag);
var sheet = styleTag.sheet;
sheet.insertRule ("@document url('http://www.google.com') { html {color:red}}", 0);

结果:

/*
Exception: SyntaxError: An invalid or illegal string was specified
@Scratchpad/3:4:0
*/

我通过@BoltClock了解了@document。

更多信息



4
是的,那个规范修改是考虑不周的,我很高兴他们推迟了它的包含。最好将其放在名为document的伪元素属性上,例如“document[url ='http://www.example.com/widgets/']", 这样可以使用所有正常的CSS属性而不是创建不同的一组属性。 开始于 ^=, 包含 *=, 结束于 $=, 等于 =。如果他们想要添加正则表达式,那么就让一个新的运算符对所有属性都可用,而不仅仅是这一个,也许是@=, %= 或者 regex - Robert McKee
@Robert McKee:伪元素是无特征,不能具有属性。此外,您将为伪元素设置样式,而不是目标元素。在我看来,使用文档规则没有问题 - 但如果更喜欢选择器,则适用于根元素的伪类会更合适。我认为,在不从根本上重新定义属性选择器(并可能破坏现有网站)的情况下,无法将属性选择器语法整合到此功能中。 - BoltClock
@BoltClock 我的意思不是工作组定义的伪元素,而是更通用的定义,类似于:root,但名称为document(或者如果您喜欢,可以使用:document)。不过,按照您提出的建议,最好直接重用:root - Robert McKee
@Robert McKee:那将是一个伪类,这也不是一个通用术语;)(我很挑剔,但两者之间的区别很重要。) - BoltClock
@BoltClock 不,我不是指像 p:url(...) 这样的伪类。而是一个存在于文档根元素更高层次的虚假/模拟(为避免使用伪名称)元素。在概念上,它是 html 元素的父级,但正如你所建议的,伪类也可以起作用,允许像 nav > a:document-url(...) 这样的构造,但这样就无法使用好看的属性选择器了。但是,一个模拟/虚假元素将允许像 document[url*='example.com'] nav > a { ... } 这样的构造。 - Robert McKee
1
@Robert McKee:嗯,这就是at-rules的用途,也是为什么这个功能被提议为at-document规则而不是选择器。 - BoltClock

3
您可以在HTML或JavaScript中将一个“data-url”自定义属性附加到元素的父级标签上,然后在CSS中查询该数据的值。下面是一个可用的示例:

const urlHolder = document.getElementById("url-holder");

document.getElementById("changer").onclick = () => {
  urlHolder.dataset.url = "https://mywebsite.com/about"
};
#url-holder[data-url*="blog"] .url-based{
  background-color: red;
}

#url-holder[data-url*="blog"] .url-based::after{
  content: "You're on the blog page!"
}

.url-based::after{
  content: "You're not on the blog page."
}

.box{
  width: 200px;
  height: 200px;
  border: 2px solid black;
  margin: 5px;
}
<button id="changer" type="button">Change data-url to "https://mywebsite.com/about"</button>
<div id="url-holder" data-url="https://mywebsite.com/blog">
  <div class="box url-based"></div>
  <div class="box not-url-based"></div>
</div>

不知道这样的解决方案性能如何。


这是一个非常创意的解决方案,谢谢。 - Reena Verma
这是一个很好的解决方案,特别适用于基于PHP的网站:将类似以下代码添加到头部模板中<body data-url="<?php $url.= $_SERVER['REQUEST_URI']; echo $url; ?>">,效果非常好。 - franklylately

2

很遗憾,没有伪类可以基于URL选择元素。唯一的方法是将类添加到body标签或特定元素,然后重写CSS。


你的CMS在body标签或包装div中没有提供这样的类吗?什么CMS? - Ideogram
@Ideogram 我想知道是否可能。我认为匹配URL与CSS将是一个很棒的功能。如果URL或URL片段更改(并且页面不重新加载),那么我可以准备好适用的CSS。我在考虑富互联网Ajax应用。 - 1.21 gigawatts

1

目前,:has()的支持相当广泛,但可能还不够高,不能没有备用方案就推出。看起来Firefox很快就会支持它,而且Chrome旧版本(低于v105)的使用量最终会下降。请参阅Can I use...https://bugzilla.mozilla.org/show_bug.cgi?id=418039

并非所有网页都会有这个功能,但在<head>中包含URL的情况相当常见,例如:

  • <link rel="canonical" href>
  • <meta property="og:url" content>
  • <meta itemprop="url" content>
  • <meta name="twitter:url" content>

将其中之一和:has()结合起来,您可以编写如下选择器:

/* URL ends with "/home.html" */
head:has(link[rel="canonical"][href$="/home.html"]) + body p {
  color: blue;
}

/* URL contains "/path/" */
head:has(link[rel="canonical"][href*="/path/"]) + body p {
  color: indigo;
}

$= & *=: 属性选择器
+: 下一个兄弟选择器


1
如果只是针对 HTML,使用 jQuery。
<script>
        var currentLocation = window.location.pathname;

        if (currentLocation == 'home.html'){
        $('head').append('<link href="home-style.css" rel="stylesheet">');
        } else if (currentLocation == 'about.html'){
        $('head').append('<link href="about-style.css" rel="stylesheet">');
        } else {
        $('head').append('<link href="index-style.css" rel="stylesheet">');
        }
    </script>

如果使用WordPress:
请在您的主题function.php文件中添加以下代码:
  function site_stil_script() {
    
    if ($_SERVER['REQUEST_URI']=='/YOURPAGE/') {
        wp_enqueue_style( 'theme_css', get_template_directory_uri() . '/assets/css/theme-difrent-style.css', array(), '20120208', 'all' );
    } else {
        wp_enqueue_style( 'theme_css', get_template_directory_uri() . '/assets/css/theme-style.css', array(), '20120208', 'all' );
    }
//other lines....
}
add_action( 'wp_enqueue_scripts', 'site_stil_script' );

0

是的!!

根据我的用例,可以使用:target CSS 伪类来实现。

https://www.w3schools.com/cssref/sel_target.php

<a href="#someid">link to current page (ends up in url after #)</a>
<div id="someid">target of previous link</div>

<style>
    #someid:target {
        background-color: green;
    }
</style>

但是对于您的用例,您需要在URL中添加类似以下内容: about.html#about home.html#home

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接