突破css选择器的局限,实现一个css地址选择器?

首先看一个效果,注意地址栏的变化

theme

然后思考一下,用css如何实现?

css选择器的局限

选择器是css中的一大特色,用于选择需要添加样式的元素。

选择器的种类有很多,比如

  • 元素选择器
p {color:gray;}
  • 类选择器
.box {color:gray;}
  • ID选择器
#title {color:gray;}
  • 属性选择器
[title] {color:gray;}
  • 后代选择器
h1 span {color:gray;}
  • 相邻兄弟选择器
h1 + p {margin-top:50px;}

这里只列举了几种,还有很多,不熟悉的可以自行搜索查找。

虽然说css选择器有很多种,可以满足绝大部分的需求,不过有时候还是会有一些看似合理,实际上比较棘手的问题。

比如说上面提到了相邻兄弟选择器,不过只能选择后面的兄弟节点,却不能选择前面的。

后代选择器,可以选择子元素,却没法选择父元素。

用另一种思维来突破局限

上面列出了两个我们常见的需求,然而css却不支持,如何解决呢?

不要在这里提js,这完全是两种不同的思维领域

这里以实现前置兄弟选择器为例

寻找关联

首先,我们需要找到和需求有关联的选择器,毕竟要以已有的选择器为基础。

这里说的有关联指的是相近或者相反,比如子选择器p>span和后代选择器p span就是比较相近的

如果要实现鼠标相关的功能,可能就会联想到:hover:active等选择器。

这里要实现前置兄弟选择器很显然需要联系上已有的相邻兄弟选择器+后置选择器~,都属于兄弟节点。

解决思路

其实有一种方式是很常见的。

比如有这样一个布局,我希望span前面的a(也就是标签1标签2)为红色字体

<div>
  <a>标签1</a>
  <a>标签2</a>
  <span>说明</span>
  <a>标签3</a>
  <a>标签4</a>
</div>

我们用到了后置选择器~,其实这里上述规定的位置关系都是以html文档中的位置为准的。

我们可以手动把这些位置颠倒一下

<div>
  <a>标签4</a>
  <a>标签3</a>
  <span>说明</span>
  <a>标签2</a>
  <a>标签1</a>
</div>

然后我们可以采取很多种方式,让页面的顺序恢复过来。

比如

a,span{
  float:right
}

这样在页面上看到的顺序还是和之前一样,分别是标签1标签2说明标签3标签4

然后就可以直接使用后置选择器~

span ~ a{
  color:red
}

这样是不是就做出了在视觉上前置选择器的效果?不过需要提前把html里面的结构反过来,通过一些样式看着顺序是正常的即可。

还有一个思路,可以称为逆向思维吧

布局和之前一样

<div>
  <a>标签1</a>
  <a>标签2</a>
  <span>说明</span>
  <a>标签3</a>
  <a>标签4</a>
</div>

我们可以这样来实现,先把所有的a都设置为红色,然后把span后面的a还原,不就达到目的了吗?

div a{
  color:red;
}
span ~ a{
  color:unset;
}

同样也实现了这样的目的。

当然这只是两个很简单的例子,详细的实例可以参考我之前写过的文章,更接近实际的需求

css地址选择器?

这里可以明确的说明,css是没有关于地址的选择器的。

这里说的地址是指浏览器的地址栏,比如

http://test.com/a

http://test.com/b

或者

http://test.com#a

http://test.com#b

有人可能觉得这是个伪需求,我的地址都变了,都不是同一个页面了,我在不同的页面分别写不同的css不就行了?

这个思路再有些情况是是对的,有些情况下有的问题

比如从http://test.com#ahttp://test.com#b这种情况下,一般都还是同一个页面

并且,现在很多单页面应用地址栏的改变并没有引起浏览器页面的刷新,地址的更变完全就是前端路由实现的,比如说我的博客

一个需求

其实我最早想到要这种选择器的时候,是做主题选择的功能。

比如http://test.comhttp://test.com#light表示正常主题,http://test.com#dark表示黑色主题。

这样做的一个好处就是可以很直观的从地址栏看出主题配色,比如可以直接以http://test.com#dark进入黑色主题。

类似的想法就是

下面是伪代码

#light div{
  background:#fff;
  color:#000;
}
#dark div{
  background:#000;
  color:#fff;
}

当然现在跟地址栏半毛钱的关系都没有。

那么,这样实现一个地址选择器?

思路

按照上面的思路,我们先考虑跟地址有关联的选择器,乍一看,确实找不到一个合适的

后来突然发现了:target选择器,这个是用来选择当前活动的 HTML 锚点的。

官方的示例也都很简单,简单来讲就是如果当前地址栏为#new,那么文档中idnew的元素就会被选中

下面是w3school的示例

http://www.w3school.com.cn/tiy/t.asp?f=css_sel_target

实现

那么怎样实现我们需要的功能呢?

这里有一个简单的布局

<div>
  <p>演示</p>
</div>

如果想实现http://test.com#dark的功能,那么文档中就应该有个iddark的元素可以选择到

<div id="dark">
  <p>演示</p>
</div>

加上id后,就可以实现类似的功能了

/**正常主题**/
p{
  background:#fff;
  color:#000;
}
/**黑色主题**/
#dark:target p{
  background:#000;
  color:#fff;
}

这么容易?

上面固定了一个,如果有多个,比如红色主题,绿色主题,黄色主题...不可能全都写在一个div上吧

<!--错误代码-->
<div id="红色" id="绿色" id="黄色">
  <p>演示</p>
</div>

这里就要区分开来了,我们需要在额外的地方来添加一些id,比如在页面的最上面

<div id="red"></div>
<div id="green"></div>
<div id="blue"></div>
<div>
  <p>演示</p>
</div>

然后结合兄弟选择器就可以实现如下效果

#red:target ~ div p{
  background:red;
}
#green:target ~ div p{
  background:green;
}
#blue:target ~ div p{
  background:blue;
}

这里是demo

效果如文章开头所示。

这里直接做了切换,源码可以右键直接查看

很简洁不是吗,也不需要本地存储,直接根据地址栏来决定主题配色。

小节

以上主要讲解了css的一些局限性,但是css足够灵活,有些地方可能是设计时候的缺陷,不可避免,但是完全可以通过其灵活性达到我们想要的效果

更先进的css4也将会到来,更多有趣的事情等着我们来发掘

插一句

还有一个更为强大的适用场景,就是多语言的适配,可以根据地址栏直接决定页面的语言

#zn:target{
  /* 一些逻辑 */
}

#en:target{
  /* 一些逻辑 */
}

#jp:target{
  /* 一些逻辑 */
}

这个后面会专门有一篇文章来讲解,敬请期待


如果喜欢我的博客,可以多多关注一下,谢谢 ~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容