首先咱們來看下頁面上須要實現的基本效果,以下圖所示:javascript
所以咱們可使用以下js代碼來試試看,是否能使用js改變僞類?以下代碼所示: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; } console.log(pos); $(".tab-content:before, .tab-content:after").css({ "left": pos }); }); });
如上代碼並不生效,所以能夠判定使用 jquery這樣單純的改變僞類樣式是行不通的。 如上有一個定位的計算方式,如上代碼,下面咱們來簡單的分析下,爲何能夠這樣計算,請看以下圖所示:html
第一個tab項的時候,小三角形的定位以下:java
點擊第二個tab項的時候,小三角形的定位以下圖所示:jquery
點擊第三個tab項的時候,小三角形的定位變爲以下圖所示:git
既然使用如上方式行不通,咱們確定須要查找資料了,正好看到有一篇文章 能解決改變css僞類樣式, 請點擊查看github
所以我這邊來詳細總結一下,如何作?那麼這邊確定須要分二種狀況,第一種是使用css內聯style樣式寫的css,第二種是外鏈的css,也就是html和css分離的那種,由於作項目的時候,分離css仍是頗有必要的。chrome
一:JS動態改變style內聯css寫的僞類樣式瀏覽器
以下代碼:app
$(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);這個;看看他有哪些屬性,以下圖所示:
而後打印 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: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下的效果以下:
再看看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下尚未測試過,若是有問題能夠留言哦!