CSS 선택 기 우선 순위 계산 깊이 이해

19090 단어 css
선택 기의 우선 순 위 는 요소 가 어떤 스타일 을 사용 하 는 지 에 달 려 있 습 니 다.CSS 2.1 의 규범 http://www.w3.org/TR/2009/CR-CSS2-20090908/cascade.html#specificity 에서 이렇게 묘사 했다.
  • 선택 기 가 있 는 규칙 이 아 닌 "style" 속성 에서 왔 다 면 1 로 기록 합 니 다. 그렇지 않 으 면 0 (= a) 으로 기록 합 니 다. (HTML 요소 의 style 속성 도 스타일 규칙 입 니 다. 이 스타일 규칙 들 은 선택 기 가 없 기 때문에 a = 1, b = 0, c = 0, d = 0)
  • 선택 기 에서 ID 속성의 개 수 를 계산 합 니 다 (= b)
  • 선택 기의 기타 속성 (클래스, 속성 선택 기) 과 위조 클래스 의 개 수 를 계산 합 니 다 (= c)
  • 선택 기 에서 요소 이름과 위조 요소 의 개 수 를 계산 합 니 다 (= d)
  • 네 개의 숫자 를 a - b - c - d 로 연결 하여 선택 기의 우선 순 위 를 구성 합 니 다.
     
    최신 Selector Level 3 규범 에서: 
  • 선택 기 에서 ID 속성의 개 수 를 계산 합 니 다 (= a)
  • 선택 기의 기타 속성 (클래스, 속성 선택 기) 과 위조 클래스 의 개 수 를 계산 합 니 다 (= b)
  • 선택 기 에서 요소 이름과 위조 요소 의 개 수 를 계산 합 니 다 (= c)
  • 유 니 버 설 선택 기 무시 *
  • 세 개의 숫자 를 a - b - c 로 연결 하여 선택 기의 우선 순 위 를 구성 합 니 다.style 속성 계산 은 css 2.1 규범 을 참고 합 니 다.
     
    질문:
    1. 선택 기의 전체 우선 순 위 는 어떻게 계산 합 니까? 인터넷 에서 말 한 a * 1000 + b * 100 + c * 10 + d 와 같 습 니까?
           답: 아니요.이런 대답 은 분명히 문 의 를 바라 보고 의 미 를 가 진 것 이다.4 급 (a, b, c, d) 간 은 단순 한 더하기 관계 가 아니다.같은 등급 (예 를 들 어 a 대 a) 의 것 만 비교 가능 한 관 계 를 가진다.
     
    분석:
    다음은 웹 키 트 의 웹 코어 에서 우선 순위 계산 에 관 한 코드 http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp 입 니 다.
    unsigned CSSSelector::specificity() const
    
    {
    
        // make sure the result doesn't overflow
    
        static const unsigned maxValueMask = 0xffffff; //          ,     :idMask + classMask + elementMak = 16777215
    
        static const unsigned idMask = 0xff0000; // ID       ,     :(16*16+16)*16^4=16711680
    
        static const unsigned classMask = 0xff00; // class(  、 )       ,     :(16*16+16)*16^2=65280
    
        static const unsigned elementMask = 0xff; //          ,     :16*16+16=255
    
    
    
        if (isForPage())
    
            return specificityForPage() & maxValueMask;
    
    
    
        unsigned total = 0;
    
        unsigned temp = 0;
    
    
    
        for (const CSSSelector* selector = this; selector; selector = selector->tagHistory()) {
    
            temp = total + selector->specificityForOneSelector();
    
            // Clamp each component to its max in the case of overflow.
    
            if ((temp & idMask) < (total & idMask)) //      ID   
    
                total |= idMask; //   ID            ID        ,  
    
            else if ((temp & classMask) < (total & classMask))
    
                total |= classMask;
    
            else if ((temp & elementMask) < (total & elementMask))
    
                total |= elementMask;
    
            else
    
                total = temp;
    
        }
    
        return total;
    
    }
    
    
    
    inline unsigned CSSSelector::specificityForOneSelector() const
    
    {
    
        // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
    
        // isn't quite correct.
    
        switch (m_match) {
    
        case Id:
    
            return 0x10000; // ID     
    
    
    
        case PseudoClass:
    
            // FIXME: PsuedoAny should base the specificity on the sub-selectors.
    
            // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html
    
            if (pseudoClassType() == PseudoClassNot && selectorList())
    
                return selectorList()->first()->specificityForOneSelector();
    
            FALLTHROUGH;
    
        case Exact:
    
        case Class:
    
        case Set:
    
        case List:
    
        case Hyphen:
    
        case PseudoElement:
    
        case Contain:
    
        case Begin:
    
        case End:
    
            return 0x100; // class     
    
    
    
        case Tag:
    
            return (tagQName().localName() != starAtom) ? 1 : 0; //        
    
        case Unknown:
    
            return 0;
    
        }
    
        ASSERT_NOT_REACHED();
    
        return 0;
    
    }

     
          위의 코드 를 통 해 알 수 있 듯 이 웹 키 트 에서 a 급 선택 기 ("style" 속성의 스타일 규칙) 는 우선 순위 연산 과정 에 참여 하지 않 습 니 다.b 급 (ID 선택 기), c 급 (class 선택 기), d 급 (요소 선택 기) 에 대해 서 는 각 단계 마다 자신의 최대 치 (최대 수 255) 가 있 고 초과 시 최대 치 (최대 수) 를 적용 합 니 다.b 급 최대 치 는 0xff 0000 (16711680) 이 고 가중치 는 0x 1000 (65536) 이 며 수량 이 256 을 초과 할 때 도 최대 치 를 사용 합 니 다.c 급, d 급 이 비슷 하 다.따라서 낮은 등급 이 일정 수 를 초과 한 후에 높 은 등급 이 1 단계 로 올 라 가 커버 되 는 상황 은 존재 하지 않 는 다.선택 기 그룹 (em: \ # a. d div) 에서 모든 선택 기의 더하기 와 167777215 를 초과 하지 않 습 니 다.demo: http://jsbin.com/duker/2 。맞다!important, webkit 는 다른 경로 (있 습 니 다! important 스타일 규칙 은 없 는 것 보다 큽 니 다! important 스타일 규칙 은 동시에 있 습 니 다! important 속성 을 가 질 때 만 선택 기의 전체 우선 순 위 를 비교 할 수 있 습 니 다).전체적으로 웹 키 트 에서!important>inline style>ID>class>tag。
          웹 키 트 는
    http://trac.webkit.org/changeset/130444/trunk/Source/WebCore/css/CSSSelector.cpp 이번 수정 에 우선 순위 가 넘 치 는 처리 (chrome 발표 버 전이 빠 르 고 올 해 는 blink 로 바 뀌 었 습 니 다. chrome 은 모두 특수성 (우선 순위) 계산 기준 을 지 켰 다 고 볼 수 있 습 니 다).
    타임 스탬프: 2012 - 10 - 04 19: 04: 44
    20 개 월 전) 저자: commt [email protected]메시지:
    선택 기 특수성 클래스 가 높 은 클래스 로 넘 침 ​https://bugs.webkit.org/show_bug.cgi?id=98295
    Patch by Tab Atkins < [email protected] > on 2012-10-04Reviewed by Eric Seidel.
    이번에 추 가 된 패 치 는 CSS 선택 기의 특수성 에 대해 넘 침 정책 을 추가 하기 위 한 것 입 니 다.
    이전에 우 리 는 각 유형의 특수성 유출 문 제 를 검사 하지 않 았 다.원본 정책 은 각 분 류 를 하나의 바이트 (2 ^ 8 = 256) 로 저장 한 다음 에 전체적으로 기호 없 는 정수 가 존재 합 니 다.이렇게 되면 256 개의 같은 유형의 단일 선택 기 는 1 개의 높 은 유형의 선택 기 와 같다.그러나 이 는 선택 기의 특수성 규칙 을 위반 해 스타일 규칙 정렬 에 문제 가 생 겼 다.
    Tests: /fast/selectors/specificity-overflow.html
  • css/CSSSelector.cpp:

  • (WebCore::CSSSelector::specificity):
     
     
          mozilla 에서 우선 순위 계산 에 관 한 코드 (주 소 는?
    http://hg.mozilla.org/mozilla-central/file/7297dedf2416/layout/style/StyleRule.cpp (472 줄 - 537 줄):
    int32_t nsCSSSelector::CalcWeightWithoutNegations() const
    
     {
    
       int32_t weight = 0;
    
     
    
     #ifdef MOZ_XUL
    
       MOZ_ASSERT(!(IsPseudoElement() &&
    
                    PseudoType() != nsCSSPseudoElements::ePseudo_XULTree &&
    
                    mClassList),
    
                  "If non-XUL-tree pseudo-elements can have class selectors "
    
                  "after them, specificity calculation must be updated");
    
     #else
    
       MOZ_ASSERT(!(IsPseudoElement() && mClassList),
    
                  "If pseudo-elements can have class selectors "
    
                  "after them, specificity calculation must be updated");
    
     #endif
    
       MOZ_ASSERT(!(IsPseudoElement() && (mIDList || mAttrList)),
    
                  "If pseudo-elements can have id or attribute selectors "
    
                  "after them, specificity calculation must be updated");
    
     
    
       if (nullptr != mCasedTag) {
    
         weight += 0x000001;
    
       }
    
       nsAtomList* list = mIDList;
    
       while (nullptr != list) {
    
         weight += 0x010000;
    
         list = list->mNext;
    
       }
    
       list = mClassList;
    
     #ifdef MOZ_XUL
    
       // XUL tree pseudo-elements abuse mClassList to store some private
    
       // data; ignore that.
    
       if (PseudoType() == nsCSSPseudoElements::ePseudo_XULTree) {
    
         list = nullptr;
    
       }
    
     #endif
    
       while (nullptr != list) {
    
         weight += 0x000100;
    
         list = list->mNext;
    
       }
    
       // FIXME (bug 561154):  This is incorrect for :-moz-any(), which isn't
    
       // really a pseudo-class.  In order to handle :-moz-any() correctly,
    
       // we need to compute specificity after we match, based on which
    
       // option we matched with (and thus also need to try the
    
       // highest-specificity options first).
    
       nsPseudoClassList *plist = mPseudoClassList;
    
       while (nullptr != plist) {
    
         weight += 0x000100;
    
         plist = plist->mNext;
    
       }
    
       nsAttrSelector* attr = mAttrList;
    
       while (nullptr != attr) {
    
         weight += 0x000100;
    
         attr = attr->mNext;
    
       }
    
       return weight;
    
     }
    
     
    
     int32_t nsCSSSelector::CalcWeight() const
    
     {
    
       // Loop over this selector and all its negations.
    
       int32_t weight = 0;
    
       for (const nsCSSSelector *n = this; n; n = n->mNegations) {
    
         weight += n->CalcWeightWithoutNegations();
    
       }
    
       return weight;
    
     }

          웹 키 트 와 마찬가지 로 inline style 요 소 는 계산 에 포함 되 지 않 습 니 다.b 급 (ID), c 급 (class), d 급 (tag) 의 최대 값 과 최소 값 도 웹 키 트 와 일치 합 니 다.다른 것 은 mozilla 에서 같은 유형의 선택 기 를 최대 치 로 제어 하지 않 고 결 과 를 직접 추가 하 는 것 이다.이렇게 되면 같은 등급 의 선택 기 수가 255 보다 많 을 때 한 단계 높 아 지 는 것, 즉 결과 가 넘 치 는 문제 가 발생 할 수 있다.또한 전체 선택 기 그룹의 우선 순위 계산 은 웹 키 트 와 유사 한 비트 와 연산 이 없 기 때문에 결과 가 넘 치지 않도록 보장 합 니 다. 간단 한 더하기 만 있 으 면 mozilla 에서 넘 치 는 문제 가 발생 할 수 있 습 니 다.
     
          IE 는 코드 를 읽 을 수 없 기 때문에 IE 시리즈 에 대해 서 는 데모 테스트 방법 으로 문 제 를 확인 할 수 밖 에 없다.모든 IE 시리즈 (q, s) 에서 표현 은 mozilla 와 일치 합 니 다.최신 IE 11 포함.
     
    주: CSS 선택 기 는 계승 성 이 있 습 니 다.
    JS Bin

    test text


    모든 브 라 우 저 에서 텍스트 는 p {font - size: 24px;} 을 사용 합 니 다.이 문장 을 지우 면 * {font - size: 40px;}, * p 를 포함 합 니 다.(계승 스타일 은 우선 순위 가 없습니다)
     
     
    결론:
    1. 우선 순위 계산 시 등급 을 뛰 어 넘 는 문 제 를 주의해 야 한다.
    2. 우선 순위 계산 은 inline style 과!important;
    3. 우선 순위 계산 은 같은 유형 만 비교 할 수 있 습 니 다 (일반적으로 255 개 이상 의 같은 선택 기 를 정의 하 는 사람 이 없습니다).
     
    참고 로 인용 하 다
    stackoverflow 위의 대답 으로 이 글 을 끝 냅 니 다.
    I am currently using the book  CSS Mastery: Advanced Web Standards Solutions .
    Chapter 1, page 16 says:
    To calculate how specific a rule is, each type of selector is assigned a numeric value. The specificity of a rule is then calculated by adding up the value of each of its selectors. Unfortunately, specificity is not calculated in base 10 but a high, unspecified, base number. This is to ensure that a highly specific selector, such as an ID selector, is never overridden by lots of less specific selectors, such as type selectors.
    참고 글:
    http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSSelector.cpp
    http://hg.mozilla.org/mozilla-central/file/17c65d32c7b8/layout/style/StyleRule.cpp#l521
    브 라 우 저의 작업 원리: 신식 웹 브 라 우 저의 배후 폭로
    KB 005: CSS 레이 어드

    좋은 웹페이지 즐겨찾기