首先我们来看下页面上需要实现的基本效果,如下图所示:

因此我们可以使用如下js代码来试试看,是否能使用js改变伪类?如下代码所示:

$(function() {
$('.listnav li').click(function(){
var index = $(this).index();
var offset = 11; // 左侧偏移 11像素
var imgWidth = 240; // 图片的宽度是240
var pos = 0;
// 因此第一个tab项的居中位置就是 240/2 + 11
if (index === 0) {
pos = imgWidth / 2 + offset + 'px';
} else {
/*
如果不是第一个tab项的话,那么计算方式就变为如下:
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
*/
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
}
console.log(pos);
$(".tab-content:before, .tab-content:after").css({ "left": pos });
});
});

如上代码并不生效,因此可以断定使用 jquery这样单纯的改变伪类样式是行不通的。 如上有一个定位的计算方式,如上代码,下面我们来简单的分析下,为什么可以这样计算,请看如下图所示:

第一个tab项的时候,小三角形的定位如下:

点击第二个tab项的时候,小三角形的定位如下图所示:

点击第三个tab项的时候,小三角形的定位变为如下图所示:

既然使用如上方式行不通,我们肯定需要查找资料了,正好看到有一篇文章 能解决改变css伪类样式, 请点击查看

因此我这边来详细总结一下,如何做?那么这边肯定需要分二种情况,第一种是使用css内联style样式写的css,第二种是外链的css,也就是html和css分离的那种,因为做项目的时候,分离css还是很有必要的。

一:JS动态改变style内联css写的伪类样式

如下代码:

$(function() {
$('.listnav li').click(function(){
var index = $(this).index();
var offset = 11; // 左侧偏移 11像素
var imgWidth = 240; // 图片的宽度是240
var pos = 0;
// 因此第一个tab项的居中位置就是 240/2 + 11
if (index === 0) {
pos = imgWidth / 2 + offset + 'px';
} else {
/*
如果不是第一个tab项的话,那么计算方式就变为如下:
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
*/
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
}
var styleSheetObject = document.getElementById('colorFlipFlop');
console.log(pos);
changeStyle(styleSheetObject, 'left', pos);
});
});
/*
* @param styleSheetObject style标签的id
* @param attr 需要改变的style属性
* @param pos 需要改变的值
*/
function changeStyle(styleSheetObject, attr, pos) {
var beforeIndex = 7; // 定位到style标签中的第几行
console.log(styleSheetObject.sheet);
console.log(styleSheetObject.sheet.cssRules[beforeIndex]);
// console.log(styleSheetObject.sheet.cssRules[beforeIndex].style[attr])
styleSheetObject.sheet.cssRules[beforeIndex].style[attr] = pos + 'px';
}

我们首先来分析下,上面的代码的含义; 在分析之前我们首先看下css的样式代码如下:

<style type="text/css" id="colorFlipFlop">
* {margin:; padding:;}
.operating-report-container {
position: relative;
width: 1000px;
margin: 30px;
border: 1px solid #ccc;
overflow: hidden;
}
.operating-report-container .listnav {
margin-left: 14px;
margin-top: 24px;
overflow: hidden;
}
.operating-report-container .listnav li {
float: left;
width: 240px;
margin-left: 33px;
cursor: pointer;
overflow: hidden;
}
.operating-report-container .listnav li .pic {
width: 240px;
height: 160px;
background: #f6f6f6;
}
.operating-report-container .listnav li .desc {
display: block;
text-align: center;
font-size: 15px;
color: #616161;
margin-top: 8px;
}
.operating-report-container .tab-content {
margin: 24px 30px;
border-top: 1px solid #e6e5e5;
position: relative;
}
.operating-report-container .tab-content:before,
.operating-report-container .tab-content:after {
bottom: 100%;
left: 131px;
border: solid transparent;
content: " ";
height:;
width:;
position: absolute;
pointer-events: none;
}
.operating-report-container .tab-content:before {
border-bottom-color: #e6e5e5;
border-width: 11px;
margin-left: -11px;
}
.operating-report-container .tab-content:after {
border-bottom-color: #fff;
border-width: 10px;
margin-left: -10px;
}
</style>

首先js代码 var styleSheetObject = document.getElementById('colorFlipFlop'); 这句代码是获取 style标签的,因为style标签上有一个id元素叫 'colorFlipFlop'。

然后我们看下打印下 console.log(styleSheetObject.sheet);这个;看看他有哪些属性,如下图所示:

然后打印 console.log(styleSheetObject.sheet.cssRules[beforeIndex]);,代码中 beforeIndex 为什么等于7呢?因此 tab-content:before 的样式在 style标签的第八行,因此为了找到 style标签的中的具体元素的位置。因为是从0开始的。如下图所示

因此最后一句代码,找到对应的元素对应的属性重新赋值,如代码:

styleSheetObject.sheet.cssRules[beforeIndex].style[attr] = pos + 'px';

如下图所示:

查看效果请点击我

二:JS动态改变使用link标签引入的伪类样式

2.1)理解 insertRule 方法的使用

首先我们先要来理解下 insertRule() 和 addRule() 这两个方法,可能很多人之前对这js中这两个方法并不熟悉,其实在研究之前,我也并不知道这两个方法的,这两个方法的作用是:向现有的样式表中添加新规则,在firefox,safari,opera和chrome中使用 insertRule()方法,该方法接收两个参数,规则文本 和 表示在哪里插入规则的索引。比如下面简单的demo:
insertRule.html 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link type="text/css" rel="stylesheet" href="./css/insertRule.css" />
<script type="text/javascript" src="./js/jquery.js"></script>
</head>
<body>
<div class="container" id="container">
欢迎光临
</div>
<script type="text/javascript" src="./js/insertRule.js"></script>
</body>
</html>

/css/insertRule.css 中的代码如下:

* {margin:; padding:;}

js/insertRule.js 代码如下:

function getStyleSheet(element) {
return element.sheet || element.styleSheet;
}
var link = document.getElementsByTagName("link")[0];
var sheet = getStyleSheet(link);
console.log(sheet)
sheet.insertRule("body { background-color: red }", 0); //DOM方法

如上js代码,先获取到页面上第一个link标签,然后对代码进行插入body的背景色的样式即可:在firefox下的效果如下:

再看看firefox下的代码如下:

然后在safari下查看下效果如下:

如上js代码,console.log(sheet) 打印的信息在firefox如下:

之前我们说过 insertRule 该方法在 firefox,safari,opera 和 chrome是支持的,但是在mac电脑下(我电脑目前是mac电脑),Chrome 66 以后的版本是不支持该属性的。如下是在我chrome中的情况,如下所示:

或者也可以请看这篇文章说的(https://www.noxxxx.com/uncaught-domexception-failed-to-execute-insertrule-on-cssstylesheet.html), 我现在chrome版本是70版本的,那也是不支持,如下我的chrome版本:

文章中说需要手动创建 style 标签插入。 因此我们的 insertRule.js 代码变为如下:

/*
function getStyleSheet(element) {
return element.sheet || element.styleSheet;
}
var link = document.getElementsByTagName("link")[0];
var sheet = getStyleSheet(link);
console.log(sheet);
sheet.insertRule("body { background-color: red }", 0); //DOM方法
*/ var stylesheet = createStyleSheet();
stylesheet.insertRule("body { background-color: red }", 0); //DOM方法 function createStyleSheet() {
var style = document.createElement('style');
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}

我们继续运行下,现在在firefox,safari,和 chrome浏览器下都支持了。chrome浏览器下的效果如下:

2.2)理解 addRule() 方法的使用

addRule方法是IE支持的一个类似的方法,该方法也是接收两个必选参数和一个可选参数:
第一个参数为:选择符文本。第二个参数为:css样式信息,第三个参数是可选的,表示的含义是:插入规则的位置,和insertRule()方法中的第二个参数类似。

基本使用方式如下:sheet.addRule("body", "background-color: red", 0); // 仅仅对IE有效

因此为了跨浏览器支持向样式表中插入规则,我们可以封装一个方法,既支持IE,也支持标准浏览器,如下代码:

/*
function getStyleSheet(element) {
return element.sheet || element.styleSheet;
}
var link = document.getElementsByTagName("link")[0];
var sheet = getStyleSheet(link);
console.log(sheet);
sheet.insertRule("body { background-color: red }", 0); //DOM方法
*/
/*
var stylesheet = createStyleSheet();
stylesheet.insertRule("body { background-color: red }", 0); //DOM方法 function createStyleSheet() {
var style = document.createElement('style');
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
*/
function createStyleSheet() {
var style = document.createElement('style');
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
function insertRule(selectorText, cssText, position) {
var stylesheet = createStyleSheet();
if (stylesheet.insertRule) {
stylesheet.insertRule(selectorText + "{" + cssText + "}", position);
} else if (stylesheet.addRule) {
stylesheet.addRule(selectorText, cssText, position);
}
}
insertRule("body", "background-color: red", 0);

请点击查看效果

所以我们现在可以使用如上的知识点,去做那个切换的demo了,index2.html代码如下

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="./css/index2.css" />
<script type="text/javascript" src="./js/jquery.js"></script>
</head>
<body>
<div class="operating-report-container" id="operating-report">
<ul class="listnav">
<li>
<div class="pic"></div>
<div class="desc">铜板街2018年度各月运营报告</div>
</li>
<li>
<div class="pic"></div>
<div class="desc">铜板街2018年度各月运营报告</div>
</li>
<li>
<div class="pic"></div>
<div class="desc">铜板街2018年度各月运营报告</div>
</li>
</ul>
<div class="tab-content" id="tab-content"> </div>
</div>
<script type="text/javascript" src="./js/index2.js"></script>
</body>
</html>

index2.js 代码如下:

$(function() {
$('.listnav li').click(function(){
var index = $(this).index();
var offset = 11; // 左侧偏移 11像素
var imgWidth = 240; // 图片的宽度是240
var pos = 0;
// 因此第一个tab项的居中位置就是 240/2 + 11
if (index === 0) {
pos = imgWidth / 2 + offset;
} else {
/*
如果不是第一个tab项的话,那么计算方式就变为如下:
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index
*/
pos = imgWidth / 2 + offset + imgWidth * index + 33 * index;
}
addRule(".operating-report-container .tab-content:before", {
left: pos + 'px'
});
addRule(".operating-report-container .tab-content:after", {
left: pos + 'px'
});
});
});
function createStyleSheet() {
var style = document.createElement('style');
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
var stylesheet = createStyleSheet();
function addRule(selector, css) {
var propText = typeof css === "string" ? css : Object.keys(css).map(function (p) {
console.log(p)
return p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p]);
}).join(";"); if (stylesheet.insertRule) {
// 标准浏览器支持的
stylesheet.insertRule(selector + "{" + propText + "}", stylesheet.cssRules.length); } else if(stylesheet.addRule) {
// IE支持的
stylesheet.addRule(selector, propText, stylesheet.cssRules.length);
}
}

如上代码封装好了的,点击查看效果

注意:如上demo目前在mac电脑上的firfox,safari,chrome测试过的,因为是mac电脑,所以在IE下还没有测试过,如果有问题可以留言哦!

查看github代码

js动态改变css伪类样式的更多相关文章

  1. jQuery如何改变css伪元素样式

    首先我们看一下css伪元素是什么: CSS 伪元素用于向某些选择器设置特殊效果. 伪元素有哪些: :first-line 伪元素:"first-line" 伪元素用于向文本的首行设 ...

  2. 动态修改 dom 元素的伪类样式

    最近写代码,需要修改伪类的 content 属性,不想定义两个样式进行切换,而是直接通过 js 进行修改. html 中的伪类(如 a:hover / a:link / class::before / ...

  3. CSS中的背景、雪碧图、超链接的伪类样式

    一.背景 1.背景颜色 background-color: red; 2.背景图片 background-image: url("../../img/l1.png"); 3.图片填 ...

  4. CSS伪类和伪元素

    一.伪类 CSS伪类用于向某些选择器添加特殊的效果,在W3规范中,CSS伪类有如下几个: CSS2.1 :active:向被激活的元素添加样式(激活是指点击鼠标那一下) :focus:向拥有键盘输入焦 ...

  5. js如何控制css伪元素内容(before,after)

    曾经遇到的问题,在对抗UC浏览器屏蔽需要把内容输出到css 伪元素中输出.有个疑问如何用js控制它.于是在segmentfault提问,如下是对问题的整理: 如何用js控制css伪类after 简单粗 ...

  6. CSS - 伪类和伪元素的区别

    伪类和伪元素皆独立于文档结构.它们获取元素的途径也不是基于id.class.属性这些基础的元素特征,而是在处于特殊状态的元素(伪类),或者是元素中特别的内容(伪元素).区别总结如下: CSS伪类 (P ...

  7. CSS伪类与CSS伪元素的区别及由来

    关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...

  8. CSS 伪类

    Link The :link CSS pseudo-class lets you select links inside elements. This will select any link whi ...

  9. 12、第十二节课,css伪类 (转)

    一.特殊选择器 1.* 用于匹配任何的标记 2.> 用于指定父子节点关系 3.E + F 毗邻元素选择器,匹配所有紧随E元素之后的同级元素F 4.E ~ F 匹配所有E元素之后的同级元素F 5. ...

随机推荐

  1. 如何用ABP框架快速完成项目(11) - ABP只要加人即可马上加快项目进展- 全栈篇(2) - 不推荐模块组件化, 推荐微服务

    一个人写代码不需要担心会和别人的代码冲突, 不需要做代码合并, 不需要担心自己的代码被覆盖. 但是多个人一起写代码就需要担心这些问题.   解决这些问题的方法很多, 比如用AzureDevOps(TF ...

  2. SQL分组函数

    分组函数是对表中的多行进行操作,而每组返回一个计算结果.常用的分组函数包括: 函数 语法格式 函数描述以及注意事项 AVG AVG([distinct|all] expr) 返回一个数字列或计算列的平 ...

  3. Mybatis使用动态代理实现拦截器功能

    1.背景介绍 拦截器顾名思义为拦截某个功能的一个武器,在众多框架中均有“拦截器”.这个Plugin有什么用呢?或者说拦截器有什么用呢?可以想想拦截器是怎么实现的.Plugin用到了Java中很重要的一 ...

  4. MFC 单文档添加按钮

    VS 单文档 添加按钮 今天做项目需要在单文档中创建按钮来响应函数,即点击按钮,调用某函数,特此记录. 1. 在XXXView中添加CButton变量,例如 CButton start; 2. 下来就 ...

  5. Apktool(3)——Apktool的使用

    一.apktool的作用 安卓应用apk文件不仅仅是包含有resource和编译的java代码的zip文件,如果你尝试用解压工具(如好压)解压后,你将会获得classes.dex和resource.a ...

  6. Linux/Unix 中 wheel 组的来源

    使用过 Linux/Unix 的朋友应该知道,将用户添加都 wheel用户组,让用户可以通过在命令在前加 sudo 临时获取 root 用户的权限.但是有没有朋友会想知道为何这个用户组要交 wheel ...

  7. java应用系统运行速度慢的解决方法

    场景:我们在部署了TOMCAT应用,刚刚开始启动的一个段时间内.访问系统的速度比较快.但是过了一段时间,应用系统就慢慢的变慢起来了.服务的访问加载时间慢慢变长. 问题解决思路: 1,查看部署应用系统的 ...

  8. 如何下载 Google Play 应用的apk

    Google Play 不能直接下载apk安装包,解决办法,安装插件下载 第一步 FQ就不说了 第二步 安装google浏览器 APK Downloader插件 第三步 打开Google play网站 ...

  9. git 使用命令删除远程分支和本地分支

    删除远程分支命令: git push origin   :<远程分支名称> git push origin --delete <远程分支名称> 删除本地分支: git bran ...

  10. Sublime Text 2 配置PHP调试环境(在windows环境下)

    1:PHP安装,配置环境变量 PHP安装略过- 2:下载Sublime Text 2 下载地址:http://www.sublimetext.com/2 ,选择自己合适的版本 3:点击 sublime ...