2008-11-22 39 views
105

Tôi đang tìm cách thay đổi các quy tắc CSS cho bộ chọn lớp giả (chẳng hạn như: liên kết,: hover, v.v.) từ JavaScript.Đặt quy tắc lớp giả CSS từ JavaScript

Vì vậy, một sự tương tự của mã CSS: a:hover { color: red } trong JS.

Tôi không thể tìm thấy câu trả lời ở bất kỳ nơi nào khác; nếu bất cứ ai biết rằng đây là một cái gì đó trình duyệt không hỗ trợ, đó sẽ là một kết quả hữu ích là tốt.

Trả lời

168

Bạn không thể tạo kiểu cho một lớp giả trên một thành phần cụ thể, giống như cách bạn không thể có một lớp giả trong thuộc tính inline style = "..." (vì không có bộ chọn nào).

Bạn có thể làm điều đó bằng cách thay đổi kiểu, ví dụ bằng cách thêm các quy tắc:

#elid:hover { background: red; } 

giả sử mỗi phần tử bạn muốn ảnh hưởng đến có một ID duy nhất để cho phép nó được chọn.

Về lý thuyết tài liệu mà bạn muốn là http://www.w3.org/TR/DOM-Level-2-Style/Overview.html có nghĩa là bạn có thể (được đưa ra một kiểu tồn tại trước đó nhúng hoặc liên kết) sử dụng cú pháp như sau:

document.styleSheets[0].insertRule('#elid:hover { background-color: red; }', 0); 
document.styleSheets[0].cssRules[0].style.backgroundColor= 'red'; 

IE, tất nhiên, đòi hỏi phải có cú pháp riêng của mình:

document.styleSheets[0].addRule('#elid:hover', 'background-color: red', 0); 
document.styleSheets[0].rules[0].style.backgroundColor= 'red'; 

Trình duyệt cũ hơn và nhỏ hơn có thể không hỗ trợ cú pháp. Bản định kiểu động-khó chơi hiếm khi được thực hiện bởi vì nó khá khó chịu để có được quyền, hiếm khi cần thiết, và lịch sử phiền hà.

+3

+1 rất cụ hữu ích – Anurag

+27

Tại sao không này chọn là câu trả lời? – SZH

+0

Các URL tham chiếu cụ thể khác: - - - ​​ –

1

Như đã nêu, đây không phải là điều mà trình duyệt hỗ trợ.

Nếu bạn không sắp xếp các kiểu động (tức là kéo chúng ra khỏi cơ sở dữ liệu hoặc thứ gì đó), bạn sẽ có thể giải quyết vấn đề này bằng cách thêm lớp vào phần nội dung của trang.

Các css sẽ giống như thế:

a:hover { background: red; } 
.theme1 a:hover { background: blue; } 

Và javascript để thay đổi điều này sẽ là một cái gì đó như:

// Look up some good add/remove className code if you want to do this 
// This is really simplified 

document.body.className += " theme1"; 
+0

Ngạc nhiên, là 'element.classList.add' không được hỗ trợ tốt ? Tôi tiếp tục thấy mọi người đang làm 'element.className + ='. –

+2

classList là một tính năng mới hơn và không giống như nó có hỗ trợ tốt cho đến gần đây (xem http://caniuse.com/classlist) –

16

Một chức năng để đối phó với những thứ qua trình duyệt:

addCssRule = function(/* string */ selector, /* string */ rule) { 
    if (document.styleSheets) { 
    if (!document.styleSheets.length) { 
     var head = document.getElementsByTagName('head')[0]; 
     head.appendChild(bc.createEl('style')); 
    } 

    var i = document.styleSheets.length-1; 
    var ss = document.styleSheets[i]; 

    var l=0; 
    if (ss.cssRules) { 
     l = ss.cssRules.length; 
    } else if (ss.rules) { 
     // IE 
     l = ss.rules.length; 
    } 

    if (ss.insertRule) { 
     ss.insertRule(selector + ' {' + rule + '}', l); 
    } else if (ss.addRule) { 
     // IE 
     ss.addRule(selector, rule, l); 
    } 
    } 
}; 
3

Thay vì trực tiếp đặt quy tắc lớp giả với javascript, bạn có thể đặt các quy tắc khác nhau trong các tệp CSS khác nhau và sau đó sử dụng Javascript để chuyển một bản định kiểu ra và chuyển sang một tệp khác. Phương pháp được mô tả tại A List Apart (qv. Để biết thêm chi tiết).

Thiết lập các tập tin CSS,

<link rel="stylesheet" href="always_on.css"> 
<link rel="stylesheet" title="usual" href="preferred.css"> <!-- on by default --> 
<link rel="alternate stylesheet" title="strange" href="alternate.css"> <!-- off by default --> 

Và sau đó chuyển đổi giữa chúng bằng cách sử javascript:

function setActiveStyleSheet(title) { 
    var i, a, main; 
    for(i=0; (a = document.getElementsByTagName("link")<i>); i++) { 
    if(a.getAttribute("rel").indexOf("style") != -1 
     && a.getAttribute("title")) { 
     a.disabled = true; 
     if(a.getAttribute("title") == title) a.disabled = false; 
    } 
    } 
} 
+0

Điều gì sẽ xảy ra nếu bạn cần thay đổi lớp học thành giá trị được yêu cầu AJAX truy xuất? Bạn không thể tạo tệp CSS ngay bây giờ ... – andreszs

29

Tôi ném cùng một small library for this vì tôi nghĩ rằng có những trường hợp sử dụng hợp lệ cho các thao tác stylesheets trong JS. Lý do là:

  • Kiểu đặt phải được tính toán hoặc truy xuất - ví dụ: đặt kích thước phông chữ ưa thích của người dùng từ cookie.
  • Đặt phong cách hành vi (không mang tính thẩm mỹ), đặc biệt là dành cho nhà phát triển tiện ích con/plugin UI. Các tab, băng chuyền, v.v. thường yêu cầu một số CSS cơ bản chỉ đơn giản là hoạt động - không nên yêu cầu biểu định kiểu cho hàm lõi.
  • Tốt hơn so với kiểu nội tuyến vì quy tắc CSS áp dụng cho tất cả các yếu tố hiện tại và tương lai và không làm lộn xộn HTML khi xem trong Công cụ dành cho nhà phát triển/Firebug.
+3

Có vẻ thực sự tốt đẹp –

4

Có một giải pháp thay thế khác. Thay vì thao tác trực tiếp các lớp giả, hãy tạo các lớp thực sự mô hình hóa cùng một thứ, như lớp "di chuột" hoặc lớp "đã truy cập". Tạo kiểu cho các lớp với thông thường "." cú pháp và sau đó bạn có thể sử dụng JavaScript để thêm hoặc xóa các lớp khỏi phần tử khi sự kiện thích hợp kích hoạt.

+1

Điều đó không có tác dụng đối với: trước và sau các lớp giả. – jbyrd

+0

Và điều đó không thể áp dụng để thay đổi hình nền với giá trị được truy xuất qua AJAX. – andreszs

+1

@jbyrd, ': before' &': after' là các phần tử giả, không phải các lớp. –

6

Bí quyết của tôi là sử dụng công cụ chọn thuộc tính. Thuộc tính dễ dàng hơn để thiết lập bởi javascript.

css

.class{ /*normal css... */} 
.class[special]:after{ content: 'what you want'} 

javascript

function setSpecial(id){ document.getElementById(id).setAttribute('special', '1'); } 

html

<element id='x' onclick="setSpecial(this.id)"> ... 
+4

Giải pháp này sử dụng jQuery - giới thiệu một phụ thuộc kích thước của jQuery cho một cái gì đó đơn giản như thế này, khi người hỏi hỏi Javascript thuần túy, là xấu. –

+0

Mặc dù pratically tất cả các trang web hiện nay sử dụng jquery, tôi sẽ sửa đổi nó để sử dụng javascript tinh khiết. –

+1

Và chính xác như thế nào phương pháp này được thay đổi các thuộc tính CSS của .class [đặc biệt]: sau phần tử giả, như, màu nền hay bất cứ thứ gì khác? – andreszs

-1

Trong jquery bạn có thể dễ dàng thiết lập di chuột các lớp giả.

$("p").hover(function(){ 
$(this).css("background-color", "yellow"); 
}, function(){ 
$(this).css("background-color", "pink"); 
}); 
-1

Nếu bạn sử dụng phản ứng, có một cái gì đó gọi là radium. Nó là như vậy hữu ích ở đây:

  • Add handlers to props if interactive styles are specified, e.g. onMouseEnter for :hover, wrapping existing handlers if necessary

  • If any of the handlers are triggered, e.g. by hovering, Radium calls setState to update a Radium-specific field on the components state object

  • On re-render, resolve any interactive styles that apply, e.g. :hover, by looking up the element's key or ref in the Radium-specific state
-1

đây là một giải pháp trong đó có hai chức năng: addCSSclass thêm một lớp css mới vào tài liệu, và toggleClass biến nó trên

Ví dụ cho thấy thêm một thanh cuộn tùy chỉnh cho một div

// If newState is provided add/remove theClass accordingly, otherwise toggle theClass 
 
function toggleClass(elem, theClass, newState) { 
 
    var matchRegExp = new RegExp('(?:^|\\s)' + theClass + '(?!\\S)', 'g'); 
 
    var add = (arguments.length > 2 ? newState : (elem.className.match(matchRegExp) === null)); 
 

 
    elem.className = elem.className.replace(matchRegExp, ''); // clear all 
 
    if (add) elem.className += ' ' + theClass; 
 
} 
 

 
function addCSSclass(rules) { 
 
    var style = document.createElement("style"); 
 
    style.appendChild(document.createTextNode("")); // WebKit hack :(
 
    document.head.appendChild(style); 
 
    var sheet = style.sheet; 
 

 
    rules.forEach((rule, index) => { 
 
    try { 
 
     if ("insertRule" in sheet) { 
 
     sheet.insertRule(rule.selector + "{" + rule.rule + "}", index); 
 
     } else if ("addRule" in sheet) { 
 
     sheet.addRule(rule.selector, rule.rule, index); 
 
     } 
 
    } catch (e) { 
 
     // firefox can break here   
 
    } 
 
    
 
    }) 
 
} 
 

 
let div = document.getElementById('mydiv'); 
 
addCSSclass([{ 
 
    selector: '.narrowScrollbar::-webkit-scrollbar', 
 
    rule: 'width: 5px' 
 
    }, 
 
    { 
 
    selector: '.narrowScrollbar::-webkit-scrollbar-thumb', 
 
    rule: 'background-color:#808080;border-radius:100px' 
 
    } 
 
]); 
 
toggleClass(div, 'narrowScrollbar', true);
<div id="mydiv" style="height:300px;width:300px;border:solid;overflow-y:scroll"> 
 
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus 
 
    a diam volutpat, ullamcorper justo eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit 
 
    nec sodales sodales. Etiam eget dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. Lorem ipsum dolor sit amet, consectetur 
 
    adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus a diam volutpat, ullamcorper justo 
 
    eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit nec sodales sodales. Etiam eget 
 
    dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. 
 
</div>

Các vấn đề liên quan