當前位置:
首頁 > 知識 > js動態改變css偽類樣式

js動態改變css偽類樣式

首先我們來看下頁面上需要實現的基本效果,如下圖所示:

js動態改變css偽類樣式

打開今日頭條,查看更多精彩圖片

因此我們可以使用如下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項的時候,小三角形的定位如下:

js動態改變css偽類樣式

點擊第二個tab項的時候,小三角形的定位如下圖所示:

js動態改變css偽類樣式

點擊第三個tab項的時候,小三角形的定位變為如下圖所示:

js動態改變css偽類樣式

既然使用如上方式行不通,我們肯定需要查找資料了,正好看到有一篇文章 能解決改變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:0; padding: 0;}
.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: 0;
width: 0;
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);這個;看看他有哪些屬性,如下圖所示:

js動態改變css偽類樣式

然後列印 console.log(styleSheetObject.sheet.cssRules[beforeIndex]);,代碼中 beforeIndex 為什麼等於7呢?因此 tab-content:before 的樣式在 style標籤的第八行,因此為了找到 style標籤的中的具體元素的位置。因為是從0開始的。如下圖所示

js動態改變css偽類樣式

因此最後一句代碼,找到對應的元素對應的屬性重新賦值,如代碼:

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

如下圖所示:

js動態改變css偽類樣式

查看效果請點擊我

二: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:0; padding: 0;}

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下的效果如下:

js動態改變css偽類樣式

再看看firefox下的代碼如下:

js動態改變css偽類樣式

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

js動態改變css偽類樣式

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

js動態改變css偽類樣式

之前我們說過 insertRule 該方法在 firefox,safari,opera 和 chrome是支持的,但是在mac電腦下(我電腦目前是mac電腦),Chrome 66 以後的版本是不支持該屬性的。如下是在我chrome中的情況,如下所示:

js動態改變css偽類樣式

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

js動態改變css偽類樣式

文章中說需要手動創建 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瀏覽器下的效果如下:

js動態改變css偽類樣式

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下還沒有測試過,如果有問題可以留言哦!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

RocketMQ源碼:通信協議設計及編解碼
Springboot2.X之切換使用Servlet容器Jetty、Tomcat、Undertow

TAG:程序員小新人學習 |