IE11-CSS 변수에 대한 polyfill / 스크립트가 있습니까?


93

혼합 웹 브라우저 환경 (Chrome / IE11)에서 웹 페이지를 개발 중입니다. IE11은 CSS 변수를 지원하지 않습니다. IE11에서 CSS 변수를 사용할 수있는 polyfill 또는 스크립트가 있습니까?


어떤 종류의 CSS 변수?
bhansa


@ R.StackUser 아래 답변 중 하나를 올바른 것으로 표시하십시오. 건배.
AndrewL64

이 사용자 정의 - 속성 - Polyfill에서 찾아 보게 github.com/nuxodin/ie11CustomProperties
토비아스 Buschor

답변:


114

예, 루트 수준 사용자 지정 속성 (IE9 +)을 처리하는 한 가능합니다.

README에서 :

풍모

  • CSS 사용자 정의 속성을 정적 값으로 클라이언트 측 변환
  • 최신 브라우저와 레거시 브라우저 모두에서 런타임 값의 실시간 업데이트
  • 변환 <link>, <style>@importCSS
  • 상대 url()경로를 절대 URL로 변환
  • 연결 및 중첩 var()함수 지원
  • var()함수 대체 값 지원
  • 웹 컴포넌트 / Shadow DOM CSS 지원
  • 시계 모드 자동 업데이트 <link><style>변경
  • UMD 및 ES6 모듈 사용 가능
  • TypeScript 정의 포함
  • 경량 (6k min + gzip) 및 종속성 없음

한계

  • 사용자 지정 속성 지원은 :root:host선언으로 제한됩니다.
  • var () 사용은 속성 값으로 제한됩니다 ( W3C 사양에 따라 ).

다음은 라이브러리가 처리 할 수있는 몇 가지 예입니다.

루트 수준 사용자 지정 속성

:root {
    --a: red;
}

p {
    color: var(--a);
}

연결된 사용자 지정 속성

:root {
    --a: var(--b);
    --b: var(--c);
    --c: red;
}

p {
    color: var(--a);
}

중첩 된 사용자 지정 속성

:root {
    --a: 1em;
    --b: 2;
}

p {
    font-size: calc(var(--a) * var(--b));
}

대체 값

p {
    font-size: var(--a, 1rem);
    color: var(--b, var(--c, var(--d, red))); 
}

변환 <link>, <style>@importCSS

<link rel="stylesheet" href="/absolute/path/to/style.css">
<link rel="stylesheet" href="../relative/path/to/style.css">

<style>
    @import "/absolute/path/to/style.css";
    @import "../relative/path/to/style.css";
</style>

웹 구성 요소 / 섀도우 DOM 변환

<custom-element>
  #shadow-root
    <style>
      .my-custom-element {
        color: var(--test-color);
      }
    </style>
    <div class="my-custom-element">Hello.</div>
</custom-element>

완전성을 위해 : w3c 사양

도움이 되었기를 바랍니다.

(뻔뻔한 자기 홍보 : 확인)


6
이것은 받아 들여진 대답이어야합니다. 코드 펜에는 기능이 부족할뿐만 아니라 최소화 된 CSS, 배경 이미지 변수, CSS의 주석 등을 처리 할 수 ​​없습니다. 광범위하게 테스트했기 때문에 알고 있습니다. @jhildenbiddle의 포니 필 사용을 권장합니다
Andres M

우수한! 감사합니다!
Tackgnol

1
@Davey-포니 필은 범위가 지정된 사용자 지정 속성을 지원하지 않으므로 --primary: #aaa선언이 처리되지 않습니다. 이 문제에 더 자세한 설명이 제공됩니다 . : root 외부에서 지원 확장 .
jhildenbiddle

2
IE의 @Davey에서는 사용자 지정 속성 값에 액세스 할 수 있지만 "-"로 시작하지 않습니다. 이것이 내 polyfill이 작동하는 방식입니다. stackoverflow.com/a/57000437/4865307
Tobias Buschor dec.

1
참고로, 이것은 대안 (ie11CustomProperties)보다 훨씬 빠르다는 것을 알았 :root습니다. 제한은 저에게 문제가되지 않습니다. 추가 성능 향상을 위해 옵션 (예 : { exclude: '[href*=jquery-ui],...', preserveStatic: false }.
Dunc

63

이 polyfill은 IE11에서 사용자 지정 속성 ( 루트 수준뿐만 아니라 )에 대한 거의 완전한 지원을 가능하게합니다 :
https://github.com/nuxodin/ie11CustomProperties

작동 원리

스크립트는 IE가 속성을 정의하고 캐스케이드를 염두에두고 읽을 수있는 최소한의 사용자 지정 속성을 지원한다는 사실을 활용합니다.
.myEl {-ie-test:'aaa'} // only one dash allowed! "-"
그런 다음 자바 스크립트로 읽으십시오.
getComputedStyle( querySelector('.myEl') )['-ie-test']

README의 기능 :

  • 동적으로 추가 된 html 콘텐츠 처리
  • 동적 추가 <style>,- <link>요소 처리
  • 체인 --bar:var(--foo)
  • 폴백 var(--color, blue)
  • : 초점, : 대상, : 호버
  • Node.js 통합 :
    • style.setProperty('--x','y')
    • style.getPropertyValue('--x')
    • getComputedStyle(el).getPropertyValue('--inherited')
  • 인라인 스타일 : <div ie-style="--color:blue"...
  • 캐스케이드 작품
  • 상속 작품
  • 3k 미만 (min + gzip) 및 종속성 없음

데모:

https://rawcdn.githack.com/nuxodin/ie11CustomProperties/b851ec2b6b8e336a78857b570d9c12a8526c9a91/test.html


1
이 폴리 필이 어떻게 사용되는지 이해하는 데 시간이 좀 걸렸습니다. README.md는 그것에 대해 명확하지 않습니다. 해결책 : <script src="yourJsPath/ie11CustomProperties.js"></script>HTML 파일의 헤드 섹션에 추가 하기 만하면 IE11이 동의합니다.
Jpsy 2019

1
의견을 보내 주셔서 감사합니다. ussage 섹션은 이제 있습니다
토비아스 Buschor

3
나에게 훨씬 더 얇은 솔루션이 올바른 접근 방식입니다. 위의 포니 필은 이전 존재 (2017 년 11 월 첫 커밋)로 인해 더 높은 등급을 받았지만 ie11CustomProperties는 2019 년 7 월에 처음 커밋되었습니다. 자신을 평가하십시오. "더 나은 품질"을 위해 더 많은 투표를 실수하지 마십시오.
digitaldonkey

9

[I has kode]의 위 질문 댓글 섹션에있는 코드 펜 스 니펫 링크에 +1. 내가 찾은 한 가지는 IE11이 불평하지 않도록 JSON 형식으로 정의 된 함수 선언을 갖도록 코드 조각을 약간 수정해야한다는 것입니다. 다음은 코드 펜 스 니펫의 약간 수정 된 버전입니다.

let cssVarPoly = {
    init: function() {
        // first lets see if the browser supports CSS variables
        // No version of IE supports window.CSS.supports, so if that isn't supported in the first place we know CSS variables is not supported
        // Edge supports supports, so check for actual variable support
        if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) {
            // this browser does support variables, abort
            console.log('your browser supports CSS variables, aborting and letting the native support handle things.');
            return;
        } else {
            // edge barfs on console statements if the console is not open... lame!
            console.log('no support for you! polyfill all (some of) the things!!');
            document.querySelector('body').classList.add('cssvars-polyfilled');
        }

        cssVarPoly.ratifiedVars = {};
        cssVarPoly.varsByBlock = {};
        cssVarPoly.oldCSS = {};

        // start things off
        cssVarPoly.findCSS();
        cssVarPoly.updateCSS();
    },

    // find all the css blocks, save off the content, and look for variables
    findCSS: function() {
        let styleBlocks = document.querySelectorAll('style:not(.inserted),link[type="text/css"]');

        // we need to track the order of the style/link elements when we save off the CSS, set a counter
        let counter = 1;

        // loop through all CSS blocks looking for CSS variables being set
        [].forEach.call(styleBlocks, function (block) {
            // console.log(block.nodeName);
            let theCSS;
            if (block.nodeName === 'STYLE') {
                // console.log("style");
                theCSS = block.innerHTML;
                cssVarPoly.findSetters(theCSS, counter);
            } else if (block.nodeName === 'LINK') {
                // console.log("link");
                cssVarPoly.getLink(block.getAttribute('href'), counter, function (counter, request) {
                    cssVarPoly.findSetters(request.responseText, counter);
                    cssVarPoly.oldCSS[counter] = request.responseText;
                    cssVarPoly.updateCSS();
                });
                theCSS = '';
            }
            // save off the CSS to parse through again later. the value may be empty for links that are waiting for their ajax return, but this will maintain the order
            cssVarPoly.oldCSS[counter] = theCSS;
            counter++;
        });
    },

    // find all the "--variable: value" matches in a provided block of CSS and add them to the master list
    findSetters: function(theCSS, counter) {
        // console.log(theCSS);
        cssVarPoly.varsByBlock[counter] = theCSS.match(/(--.+:.+;)/g) || [];
    },

    // run through all the CSS blocks to update the variables and then inject on the page
    updateCSS: function() {
        // first lets loop through all the variables to make sure later vars trump earlier vars
        cssVarPoly.ratifySetters(cssVarPoly.varsByBlock);

        // loop through the css blocks (styles and links)
        for (let curCSSID in cssVarPoly.oldCSS) {
            // console.log("curCSS:",oldCSS[curCSSID]);
            let newCSS = cssVarPoly.replaceGetters(cssVarPoly.oldCSS[curCSSID], cssVarPoly.ratifiedVars);
            // put it back into the page
            // first check to see if this block exists already
            if (document.querySelector('#inserted' + curCSSID)) {
                // console.log("updating")
                document.querySelector('#inserted' + curCSSID).innerHTML = newCSS;
            } else {
                // console.log("adding");
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = newCSS;
                style.classList.add('inserted');
                style.id = 'inserted' + curCSSID;
                document.getElementsByTagName('head')[0].appendChild(style);
            }
        };
    },

    // parse a provided block of CSS looking for a provided list of variables and replace the --var-name with the correct value
    replaceGetters: function(curCSS, varList) {
        // console.log(varList);
        for (let theVar in varList) {
            // console.log(theVar);
            // match the variable with the actual variable name
            let getterRegex = new RegExp('var\\(\\s*' + theVar + '\\s*\\)', 'g');
            // console.log(getterRegex);
            // console.log(curCSS);
            curCSS = curCSS.replace(getterRegex, varList[theVar]);

            // now check for any getters that are left that have fallbacks
            let getterRegex2 = new RegExp('var\\(\\s*.+\\s*,\\s*(.+)\\)', 'g');
            // console.log(getterRegex);
            // console.log(curCSS);
            let matches = curCSS.match(getterRegex2);
            if (matches) {
                // console.log("matches",matches);
                matches.forEach(function (match) {
                    // console.log(match.match(/var\(.+,\s*(.+)\)/))
                    // find the fallback within the getter
                    curCSS = curCSS.replace(match, match.match(/var\(.+,\s*(.+)\)/)[1]);
                });

            }

            // curCSS = curCSS.replace(getterRegex2,varList[theVar]);
        };
        // console.log(curCSS);
        return curCSS;
    },

    // determine the css variable name value pair and track the latest
    ratifySetters: function(varList) {
        // console.log("varList:",varList);
        // loop through each block in order, to maintain order specificity
        for (let curBlock in varList) {
            let curVars = varList[curBlock];
            // console.log("curVars:",curVars);
            // loop through each var in the block
            curVars.forEach(function (theVar) {
                // console.log(theVar);
                // split on the name value pair separator
                let matches = theVar.split(/:\s*/);
                // console.log(matches);
                // put it in an object based on the varName. Each time we do this it will override a previous use and so will always have the last set be the winner
                // 0 = the name, 1 = the value, strip off the ; if it is there
                cssVarPoly.ratifiedVars[matches[0]] = matches[1].replace(/;/, '');
            });
        };
        // console.log(ratifiedVars);
    },

    // get the CSS file (same domain for now)
    getLink: function(url, counter, success) {
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.overrideMimeType('text/css;');
        request.onload = function () {
            if (request.status >= 200 && request.status < 400) {
                // Success!
                // console.log(request.responseText);
                if (typeof success === 'function') {
                    success(counter, request);
                }
            } else {
                // We reached our target server, but it returned an error
                console.warn('an error was returned from:', url);
            }
        };

        request.onerror = function () {
            // There was a connection error of some sort
            console.warn('we could not get anything from:', url);
        };

        request.send();
    }

};

cssVarPoly.init();

3

이 버전의 Polyfill을 시도했지만 CSS의 한 줄에 여러 변수 (FI 글꼴 및 색상)가있을 때 오류가 발생했습니다. 제 동료가 저를 도와주었습니다. 94 행을 참조하십시오.

let cssVarPoly = {
    init: function() {
        // first lets see if the browser supports CSS variables
        // No version of IE supports window.CSS.supports, so if that isn't supported in the first place we know CSS variables is not supported
        // Edge supports supports, so check for actual variable support
        if (window.CSS && window.CSS.supports && window.CSS.supports('(--foo: red)')) {
            // this browser does support variables, abort
            // console.log('your browser supports CSS variables, aborting and letting the native support handle things.');
            return;
        } else {
            // edge barfs on console statements if the console is not open... lame!
            // console.log('no support for you! polyfill all (some of) the things!!');
            document.querySelector('body').classList.add('cssvars-polyfilled');
        }

        cssVarPoly.ratifiedVars = {};
        cssVarPoly.varsByBlock = {};
        cssVarPoly.oldCSS = {};

        // start things off
        cssVarPoly.findCSS();
        cssVarPoly.updateCSS();
    },

    // find all the css blocks, save off the content, and look for variables
    findCSS: function() {
        let styleBlocks = document.querySelectorAll('style:not(.inserted),link[type="text/css"]');

        // we need to track the order of the style/link elements when we save off the CSS, set a counter
        let counter = 1;

        // loop through all CSS blocks looking for CSS variables being set
        [].forEach.call(styleBlocks, function (block) {
            // console.log(block.nodeName);
            let theCSS;
            if (block.nodeName === 'STYLE') {
                // console.log("style");
                theCSS = block.innerHTML;
                cssVarPoly.findSetters(theCSS, counter);
            } else if (block.nodeName === 'LINK') {
                // console.log("link");
                cssVarPoly.getLink(block.getAttribute('href'), counter, function (counter, request) {
                    cssVarPoly.findSetters(request.responseText, counter);
                    cssVarPoly.oldCSS[counter] = request.responseText;
                    cssVarPoly.updateCSS();
                });
                theCSS = '';
            }
            // save off the CSS to parse through again later. the value may be empty for links that are waiting for their ajax return, but this will maintain the order
            cssVarPoly.oldCSS[counter] = theCSS;
            counter++;
        });
    },

    // find all the "--variable: value" matches in a provided block of CSS and add them to the master list
    findSetters: function(theCSS, counter) {
        // console.log(theCSS);
        cssVarPoly.varsByBlock[counter] = theCSS.match(/(--.+:.+;)/g) || [];
    },

    // run through all the CSS blocks to update the variables and then inject on the page
    updateCSS: function() {
        // first lets loop through all the variables to make sure later vars trump earlier vars
        cssVarPoly.ratifySetters(cssVarPoly.varsByBlock);

        // loop through the css blocks (styles and links)
        for (let curCSSID in cssVarPoly.oldCSS) {
            // console.log("curCSS:",oldCSS[curCSSID]);
            let newCSS = cssVarPoly.replaceGetters(cssVarPoly.oldCSS[curCSSID], cssVarPoly.ratifiedVars);
            // put it back into the page
            // first check to see if this block exists already
            if (document.querySelector('#inserted' + curCSSID)) {
                // console.log("updating")
                document.querySelector('#inserted' + curCSSID).innerHTML = newCSS;
            } else {
                // console.log("adding");
                var style = document.createElement('style');
                style.type = 'text/css';
                style.innerHTML = newCSS;
                style.classList.add('inserted');
                style.id = 'inserted' + curCSSID;
                document.getElementsByTagName('head')[0].appendChild(style);
            }
        };
    },

    // parse a provided block of CSS looking for a provided list of variables and replace the --var-name with the correct value
    replaceGetters: function(curCSS, varList) {
        // console.log(varList);
        for (let theVar in varList) {
            // console.log(theVar);
            // match the variable with the actual variable name
            // console.log (theVar);
            var res = theVar.match(/--[a-zA-Z0-9-]+/g);
            // console.log (res[0]);
            theVar = res[0];
            let getterRegex = new RegExp('var\\(\\s*' + theVar + '\\s*\\)', 'g');
            // console.log(getterRegex);
            // console.log(curCSS);
            curCSS = curCSS.replace(getterRegex, varList[theVar]);

            // now check for any getters that are left that have fallbacks
            let getterRegex2 = new RegExp('var\\(\\s*.+\\s*,\\s*(.+)\\)', 'g');
            // console.log(getterRegex);
            // console.log(curCSS);
            let matches = curCSS.match(getterRegex2);
            if (matches) {
                // console.log("matches",matches);
                matches.forEach(function (match) {
                    // console.log(match.match(/var\(.+,\s*(.+)\)/))
                    // find the fallback within the getter
                    curCSS = curCSS.replace(match, match.match(/var\(.+,\s*(.+)\)/)[1]);
                });
            }

            // curCSS = curCSS.replace(getterRegex2,varList[theVar]);
        };
        // console.log(curCSS);
        return curCSS;
    },

    // determine the css variable name value pair and track the latest
    ratifySetters: function(varList) {
        // console.log("varList:",varList);
        // loop through each block in order, to maintain order specificity
        for (let curBlock in varList) {
            let curVars = varList[curBlock];
            // console.log("curVars:",curVars);
            // loop through each var in the block
            curVars.forEach(function (theVar) {
                // console.log(theVar);
                // split on the name value pair separator
                let matches = theVar.split(/:\s*/);
                // console.log(matches);
                // put it in an object based on the varName. Each time we do this it will override a previous use and so will always have the last set be the winner
                // 0 = the name, 1 = the value, strip off the ; if it is there
                cssVarPoly.ratifiedVars[matches[0]] = matches[1].replace(/;/, '');
            });
        };
        // console.log(ratifiedVars);
    },

    // get the CSS file (same domain for now)
    getLink: function(url, counter, success) {
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.overrideMimeType('text/css;');
        request.onload = function () {
            if (request.status >= 200 && request.status < 400) {
                // Success!
                // console.log(request.responseText);
                if (typeof success === 'function') {
                    success(counter, request);
                }
            } else {
                // We reached our target server, but it returned an error
                console.warn('an error was returned from:', url);
            }
        };

        request.onerror = function () {
            // There was a connection error of some sort
            console.warn('we could not get anything from:', url);
        };

        request.send();
    }

};

cssVarPoly.init();

0

Internet Explorer를 지원하려면 index.html 헤드 태그에서 아래 스크립트를 사용하면 매력적으로 작동합니다.

<script>window.MSInputMethodContext && document.documentMode && document.write('<script src="https://cdn.jsdelivr.net/gh/nuxodin/ie11CustomProperties@4.1.0/ie11CustomProperties.min.js"><\x2fscript>');</script>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.