JavaScript에서 CSS 의사 클래스 규칙 설정


125

JavaScript에서 의사 클래스 선택기 (예 : : link, : hover 등)에 대한 CSS 규칙을 변경하는 방법을 찾고 있습니다.

따라서 CSS 코드의 아날로그 : a:hover { color: red }JS에서.

다른 곳에서는 답을 찾을 수 없었습니다. 이것이 브라우저가 지원하지 않는 것임을 아는 사람이 있다면 도움이 될 것입니다.

답변:


192

인라인 style = "..."속성에 의사 클래스를 가질 수없는 것과 같은 방식으로 (선택자가 없기 때문에) 특정 요소에서만 의사 클래스의 스타일을 지정할 수 없습니다.

예를 들어 규칙을 추가하여 스타일 시트를 변경하여이를 수행 할 수 있습니다.

#elid:hover { background: red; }

영향을 미치려는 각 요소에 선택할 수있는 고유 ID가 있다고 가정합니다.

이론상 원하는 문서는 http://www.w3.org/TR/DOM-Level-2-Style/Overview.html 입니다. 즉, 다음과 같은 구문을 사용하여 (기존의 삽입 또는 링크 된 스타일 시트가있는 경우) 가능합니다.

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

물론 IE에는 자체 구문이 필요합니다.

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

이전 및 부 브라우저는 두 구문을 모두 지원하지 않을 수 있습니다. 동적 스타일 시트 조작은 제대로하기가 매우 성 가시고, 거의 필요하지 않으며, 역사적으로 번거롭기 때문에 거의 수행되지 않습니다.


32
왜 이것이 답으로 선택되지 않았습니까?
SZH 2011 년


2
Firefox : "오류 : 작업이 안전하지 않습니다."
8128

@fluteflute 다른 도메인에서 CSS 파일을 조작하려는 경우 작업이 안전하지 않은 것으로 간주됩니다 (동일 출처 정책의 한 유형 인 것 같습니다). 부끄러움! 확인하는 간단한 기능이 동일 출처 정책을 준수합니다. function sameOrigin(url) { var loc = window.location, a = document.createElement('a'); a.href = url; return a.hostname === loc.hostname && a.port === loc.port && a.protocol === loc.protocol; }
WickyNilliams

3
스타일 시트가 변경 될 때마다 브라우저가 전체 문서를 리플 로우하므로 특정 요소에 스타일을 적용하기 위해 스타일 시트를 조작하는 것은 권장되지 않습니다. stubbornella.org/content/2009/03/27/…
Johannes Ewald

29

JS에서 스타일 시트를 조작하는 데 유효한 사용 사례가 있다고 생각 하기 때문에 이를 위해 작은 라이브러리를 모았습니다 . 이유 :

  • 계산하거나 검색해야하는 스타일 설정 (예 : 쿠키에서 사용자가 선호하는 글꼴 크기 설정)
  • 특히 UI 위젯 / 플러그인 개발자를위한 행동 (미적 아님) 스타일 설정. 탭, 캐 러셀 등은 단순히 작동하기 위해 기본 CSS가 필요한 경우가 많습니다 . 핵심 기능에 대한 스타일 시트를 요구 해서는 안됩니다 .
  • CSS 규칙이 현재 및 미래의 모든 요소에 적용되고 Firebug / 개발자 도구에서 볼 때 HTML을 어지럽히 지 않기 때문에 인라인 스타일보다 좋습니다.

17

브라우저 간 문제에 대처하는 기능 :

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);
    }
  }
};

7

템플릿 문자열에 CSS를 넣으십시오.

const cssTemplateString = `.foo:[psuedoSelector]{prop: value}`;

그런 다음 스타일 요소를 만들고 스타일 태그에 문자열을 배치하고 문서에 첨부합니다.

const styleTag = document.createElement("style");
styleTag.innerHTML = cssTemplateString;
document.head.insertAdjacentElement('beforeend', styleTag);

특이성이 나머지를 처리합니다. 그런 다음 스타일 태그를 동적으로 제거하고 추가 할 수 있습니다. 이것은 라이브러리에 대한 간단한 대안이며 DOM의 스타일 시트 배열을 엉망으로 만듭니다. 행복한 코딩!


insertAdjacentElement주요 브라우저 (Chrome, Firefox, Edge)에서 2 개의 인수가 필요하며, 그중 첫 번째는 참조 요소와 관련된 위치를 설정합니다 ( 여기 참조 ). 최근 변경 사항입니까? (답변에 'beforeend'추가).
collapsar

6

내 트릭은 속성 선택기를 사용하는 것입니다. 속성은 자바 스크립트로 설정하기가 더 쉽습니다.

CSS

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

자바 스크립트

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

HTML

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

4
이 솔루션은 jQuery를 사용합니다. 질문자가 순수한 Javascript를 요청했을 때 이와 같이 단순한 것에 대해 jQuery 크기의 종속성을 도입하는 것은 좋지 않습니다.
Tom Ashworth 2013 년

요즘은 거의 모든 웹 사이트에서 jquery를 사용하지만 순수한 자바 스크립트를 사용하도록 수정하겠습니다.
Sergio Abreu 2013 년

1
그리고 정확히 어떻게이 메서드가 .class [special] : after 가상 요소 (예 : 배경색 또는 다른 것)의 CSS 속성을 변경합니까?
andreszs

5

또 다른 대안이 있습니다. 의사 클래스를 직접 조작하는 대신 "hover"클래스 또는 "visited"클래스와 같이 동일한 것을 모델링하는 실제 클래스를 만듭니다. 일반적인 "."로 클래스 스타일을 지정합니다. 그런 다음 적절한 이벤트가 발생하면 JavaScript를 사용하여 요소에서 클래스를 추가하거나 제거 할 수 있습니다.


2
: before 및 : after 의사 클래스에는 작동하지 않습니다.
jbyrd

그리고 AJAX를 통해 검색된 값으로 배경 이미지를 변경하는 데는 적용되지 않습니다.
andreszs

1
@jbyrd, :before& :after는 클래스가 아니라 의사 요소입니다.
Roy Ling

@royling-예, 수정 해 주셔서 감사합니다! 내 댓글을 수정할 수없는 것 같습니다.
jbyrd

4

자바 스크립트로 의사 클래스 규칙을 직접 설정하는 대신 다른 CSS 파일에서 규칙을 다르게 설정 한 다음 자바 스크립트를 사용하여 한 스타일 시트를 끄고 다른 스타일 시트를 켤 수 있습니다. 방법은 A List Apart (자세한 내용은 qv.)에 설명되어 있습니다.

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 -->

그런 다음 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;
     }
   }
}

클래스를 AJAX 요청에 의해 검색된 값으로 동적으로 변경해야하는 경우 어떻게합니까? 이제 CSS 파일을 만들 수 없습니다 ...
andreszs

2

이미 언급했듯이 이것은 브라우저가 지원하는 것이 아닙니다.

스타일이 동적으로 나오지 않는 경우 (즉, 데이터베이스 등에서 가져 오기) 페이지 본문에 클래스를 추가하여이 문제를 해결할 수 있습니다.

CSS는 다음과 같습니다.

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

그리고 이것을 변경하는 자바 스크립트는 다음과 같습니다.

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

document.body.className += " theme1";  

호기심에서 element.classList.add잘 지원되지 않습니까? 나는 사람들이하는 것을 계속 봅니다 element.className +=.
Joel Cornett 2014 년

2
classList는 새로운 기능이며 (참조가 최근 상당히까지 좋은 지원이 있었다처럼 보이지 않는 caniuse.com/classlist를 )
나다니엘 라인 하트


-1

jquery에서는 호버 의사 클래스를 쉽게 설정할 수 있습니다.

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

-1

다음은 두 가지 기능을 포함하는 솔루션입니다. addCSSclass는 문서에 새 CSS 클래스를 추가하고 toggleClass는이를 켭니다.

예제는 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>


-2

REACT를 사용하면 라듐 이라는 것이 있습니다 . 여기에서 매우 유용합니다.

  • 대화 형 스타일이 지정된 경우 소품에 처리기를 추가합니다. 예를 들어 : hover에 대한 onMouseEnter, 필요한 경우 기존 처리기를 래핑합니다.

  • 핸들러 중 하나라도 호버링으로 트리거되는 경우 Radium은 setState를 호출하여 구성 요소 상태 개체의 Radium 관련 필드를 업데이트합니다.

  • 다시 렌더링 할 때 적용되는 대화식 스타일 (예 : : hover)을 확인하여 Radium 관련 상태에서 요소의 키 또는 참조를 조회합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.