ตัวแปรเนทีฟ CSS ไม่ทำงานในการสืบค้นสื่อ


141

ฉันพยายามใช้ตัวแปร CSS ในการสืบค้นสื่อ แต่ไม่ได้ผล

:root {
  --mobile-breakpoint: 642px;
}

@media (max-width: var(--mobile-breakpoint)) {

}

คุณลองใช้เบราว์เซอร์หลายตัวหรือยัง? (เช่น Chrome และ Firefox)
Cohars

1
@sandrinaPereira
Cohars

1
@SandrinaPereira ดังนั้นคุณสามารถทำได้บน Firefox และ Chrome 👍
Cohars


4
เพียงเพื่อชี้แจงสำหรับผู้ที่พบสิ่งนี้ผ่าน Google: คุณสามารถใช้คุณสมบัติที่กำหนดเองของ CSS ภายในขอบเขตของข้อความค้นหาสื่อคุณไม่สามารถใช้คุณสมบัติเหล่านี้ในการประกาศแบบสอบถามสื่อได้
David Deprost

คำตอบ:


114

จากสเป็ค ,

var()ฟังก์ชั่นสามารถนำมาใช้ในสถานที่ของส่วนหนึ่งของค่าใด ๆ ในทรัพย์สินใด ๆ เกี่ยวกับองค์ประกอบ var()ฟังก์ชั่นไม่สามารถนำมาใช้เป็นชื่อคุณสมบัติเตอร์หรือสิ่งอื่นนอกเหนือจากค่าทรัพย์สิน (การทำเช่นนี้มักจะสร้างไวยากรณ์ที่ไม่ถูกต้องหรือมิฉะนั้นค่าที่ความหมายไม่มีส่วนเกี่ยวข้องกับตัวแปร)

ไม่คุณไม่สามารถใช้ในแบบสอบถามสื่อได้

และนั่นก็สมเหตุสมผล เนื่องจากคุณสามารถตั้งค่า--mobile-breakpointเช่นเป็น:rootนั่นคือ<html>องค์ประกอบและจากนั้นจะสืบทอดไปยังองค์ประกอบอื่น ๆ แต่แบบสอบถามสื่อไม่ใช่องค์ประกอบไม่ได้รับการสืบทอดมา<html>จึงไม่สามารถทำงานได้

นี่ไม่ใช่สิ่งที่ตัวแปร CSS พยายามทำให้สำเร็จ คุณสามารถใช้ตัวประมวลผลล่วงหน้า CSS แทนได้


78
คำตอบนั้นถูกต้องเนื่องจากในขณะนี้ข้อมูลจำเพาะไม่ได้จัดการกับตัวแปร CSS ในการสืบค้นสื่อ แต่สิ่งที่ไม่ถูกต้องนั้นไม่ใช่สิ่งที่ตัวแปร CSS พยายามทำให้สำเร็จ การลดการทำซ้ำและจำนวนเวทย์มนตร์เป็นสาเหตุที่ทำให้ตัวแปร CSS ถูกสร้างขึ้น - ดูw3.org/TR/css-variables-1/#intro
mikemaccana

69

ตามที่Oriol ได้ตอบไว้ปัจจุบันตัวแปร CSS ระดับ 1 var()ไม่สามารถใช้ในการสืบค้นสื่อได้ อย่างไรก็ตามมีความคืบหน้าล่าสุดที่จะแก้ไขปัญหานี้ ในอีกไม่กี่ปีหลังจากCSS Environment Variables Module Level 1 ได้รับการปรับมาตรฐานและนำไปใช้แล้วเราจะสามารถใช้env()ตัวแปรในการสืบค้นสื่อในเบราว์เซอร์สมัยใหม่ทั้งหมดได้

หากคุณอ่านข้อกำหนดและมีข้อกังวลหรือหากคุณต้องการแสดงความสนับสนุนสำหรับกรณีการใช้งานแบบสอบถามสื่อคุณยังสามารถทำได้ในGitHub w3c / csswg-drafts # 1693หรือในปัญหา CSS GitHub ที่ขึ้นต้นด้วย“ [ CSS-env-1]”


คำตอบเดิม2017/11/09 : เมื่อเร็ว ๆ นี้คณะทำงาน CSS ตัดสินใจว่าตัวแปร CSS ระดับ 2 จะให้การสนับสนุนผู้ใช้กำหนดตัวแปรสภาพแวดล้อมการใช้env()และพวกเขาจะพยายามที่จะทำให้พวกเขาถูกต้องในคำสั่งสื่อ กลุ่มแก้ไขปัญหานี้หลังจากที่ Apple เสนอคุณสมบัติตัวแทนผู้ใช้มาตรฐานเป็นครั้งแรกก่อนการประกาศอย่างเป็นทางการของ iPhone X ในเดือนกันยายน 2017 (ดูWebKit:“ การออกแบบเว็บไซต์สำหรับ iPhone X” โดย Timothy Horton ) จากนั้นตัวแทนของเบราว์เซอร์อื่น ๆ ก็เห็นด้วยว่าโดยทั่วไปแล้วพวกเขาจะมีประโยชน์ในอุปกรณ์ต่างๆเช่นจอโทรทัศน์และการพิมพ์หมึกที่มีขอบตก ( env()เคยเรียกconstant()แต่ตอนนี้เลิกใช้แล้ว คุณอาจยังคงเห็นบทความที่อ้างถึงชื่อเก่าเช่นบทความนี้โดย Peter-Paul Koch ) หลังจากผ่านไปหลายสัปดาห์Cameron McCormack จาก Mozilla ก็ตระหนักว่าตัวแปรสภาพแวดล้อมเหล่านี้สามารถใช้งานได้ในการสืบค้นของสื่อและTab Atkins, Jr. จากนั้น Google ได้ตระหนักว่าตัวแปรสภาพแวดล้อมที่ผู้ใช้กำหนดเองจะมีประโยชน์อย่างยิ่งในฐานะตัวแปรรูทส่วนกลางที่ไม่สามารถเขียนทับได้ซึ่งใช้ในการสืบค้นสื่อ ตอนนี้Dean“ Dino” Jackson จาก Apple จะเข้าร่วม Atkinsในการแก้ไขระดับ 2

คุณสามารถสมัครรับการปรับปรุงในเรื่องนี้ในw3c/csswg-draftsGitHub รุ่น # (สำหรับรายละเอียดทางประวัติศาสตร์ที่เกี่ยวข้องโดยเฉพาะให้ขยายบันทึกการประชุมที่ฝังอยู่ในมติของ CSSWG Meeting Botและค้นหา "MQ" ซึ่งย่อมาจาก "media queries")

ฉันวางแผนที่จะอัปเดตคำถามนี้ในอนาคตเมื่อมีการพัฒนาเพิ่มเติม อนาคตเป็นเรื่องที่น่าตื่นเต้น


อัปเดต2018-02-08 : Safari Technology Preview 49ได้เพิ่มการรองรับสำหรับการแยกวิเคราะห์calc()ในการสืบค้นสื่อซึ่งอาจเป็นการนำไปสู่การสนับสนุนenv()เช่นกัน


ปรับปรุง2018/04/27 : ทีมโครเมี่ยมที่ Google env()ได้ตัดสินใจที่จะเริ่มต้นการทำงานใน ในการตอบสนองแอตกินส์ได้เริ่มต้นในการระบุenv()ในการแยกร่างมาตรฐานทางการที่: CSS ตัวแปรสภาพแวดล้อมโมดูลระดับ 1 (ดูความคิดเห็น GitHub ของเขาใน w3c / csswg-drafts # 1693และความคิดเห็นของเขาใน w3c / csswg-drafts # 1817 ) แบบร่างเรียกตัวแปรในการสืบค้นสื่อว่าเป็นกรณีการใช้งานที่ชัดเจน:

เนื่องจากตัวแปรสภาพแวดล้อมไม่ได้ขึ้นอยู่กับค่าของสิ่งที่ดึงมาจากองค์ประกอบใดองค์ประกอบหนึ่งจึงสามารถใช้ในสถานที่ที่ไม่มีองค์ประกอบที่ชัดเจนให้ดึงออกมาเช่นใน@mediaกฎซึ่งvar()ฟังก์ชันจะไม่ถูกต้อง

หากคุณอ่านข้อกำหนดและมีข้อกังวลหรือหากคุณต้องการแสดงความสนับสนุนสำหรับกรณีการใช้งานแบบสอบถามสื่อคุณยังสามารถทำได้ในGitHub w3c / csswg-drafts # 1693หรือในปัญหา CSS GitHub ที่ขึ้นต้นด้วย“ [ CSS-env-1]”


อัปเดต2019-07-06 : ทำงานต่อไปตามข้อกำหนด GitHub issue # 2627และGitHub issue # 3578ใช้สำหรับตัวแปรสภาพแวดล้อมที่กำหนดเองในการสืบค้นสื่อ


32

สิ่งที่คุณทำได้คือ @media ค้นหาคำสั่ง: root!

:root {
     /* desktop vars */
}
@media screen and (max-width: 479px) {
    :root {
        /* mobile vars */
    }
}

ใช้งานได้ทั้งหมดใน Chrome, Firefox และ Edge อย่างน้อยเวอร์ชันการผลิตล่าสุด ณ โพสต์นี้


ว้าวขอบคุณ! นี่น่าจะเป็นคำตอบที่ถูกต้องแน่นอน
SimplyComplexable

1
ดีแล้วที่รู้. ข้อ จำกัด ประการหนึ่ง: หากจำเป็นต้องเข้าถึงค่านั้นเป็น a varดังนั้นจึงสามารถใช้ในการคำนวณที่อื่นในส่วนcssนี้ได้ก็ยังต้องใส่ "ค่าวิเศษ" (ที่นี่คือ 479px) ในสองตำแหน่ง: คิวรีสื่อและการประกาศ var
ToolmakerSteve

8

เห็นได้ชัดว่ามันเป็นไปไม่ได้ที่จะใช้ตัวแปร CSS ดั้งเดิมเช่นนั้น มันเป็นข้อ จำกัดอย่างหนึ่ง

วิธีที่ชาญฉลาดในการใช้คือการเปลี่ยนตัวแปรของคุณในแบบสอบถามสื่อเพื่อให้ส่งผลต่อสไตล์ของคุณทั้งหมด ผมขอแนะนำให้บทความนี้

:root {
  --gutter: 4px;
}

section {
  margin: var(--gutter);
}

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}

ฉันไม่เข้าใจความหมายของ "เปลี่ยนตัวแปรของคุณในแบบสอบถามสื่อ" คุณสามารถแสดงตัวอย่าง?

1
นี่ไม่ใช่สิ่งที่ฉันหมายถึง ฉันถามเกี่ยวกับค่าแบบสอบถามสื่อ

4
ใช่แล้วมันอยู่ในบทความที่ฉันเชื่อมโยง ฉันรู้ว่ามันไม่ใช่สิ่งที่คุณคาดหวัง แต่ตัวแปร CSS ไม่สามารถใช้เพื่อกำหนดการสืบค้นสื่อได้
Cohars

8

postcss-media-variablesวิธีหนึ่งที่จะบรรลุสิ่งที่คุณต้องการใช้แพคเกจ NPM

หากคุณพอใจกับการใช้แพ็คเกจ npm คุณสามารถดู documentatoin ได้ที่นี่

ตัวอย่าง

/* input */
:root {
  --min-width: 1000px;
  --smallscreen: 480px;
}
@media (min-width: var(--min-width)) {}
@media (max-width: calc(var(--min-width) - 1px)) {}

@custom-media --small-device (max-width: var(--smallscreen));
@media (--small-device) {}

4
ขอบคุณ แต่ฉันพยายามไม่ใช้ตัวประมวลผลล่วงหน้าใด ๆ

et อัล: ด้วย postcss คุณยังสามารถใช้ cssnext cssnext.io/features/#custom-media-queries
sebilasse

1
@sebilasse: custom-media-queriesไม่ได้แก้ปัญหาหลักของการไม่สามารถใช้ตัวแปร css เป็นจุดพักสำหรับการสืบค้นสื่อ
zhirzh

1
postcss ไม่ใช่ตัวประมวลผลล่วงหน้า

1

เนื่องจากคุณสามารถอ่านคำตอบอื่น ๆ ได้ แต่ก็ยังไม่สามารถทำได้

มีคนพูดถึงตัวแปรสภาพแวดล้อมที่กำหนดเอง (คล้ายกับตัวแปร css ที่กำหนดเองenv()แทนที่จะเป็นvar()) และหลักการก็ฟังดูดีแม้ว่าจะยังมี 2 ประเด็นหลัก:

  • การสนับสนุนเบราว์เซอร์ที่อ่อนแอ
  • จนถึงขณะนี้ไม่มีวิธีใดที่จะกำหนดได้ (แต่อาจจะเป็นไปในอนาคตเนื่องจากเป็นเพียงร่างที่ไม่เป็นทางการเท่านั้น)

1

คำตอบสั้น ๆ

คุณสามารถใช้ JavaScript เพื่อเปลี่ยนค่าของคิวรีสื่อและตั้งเป็นค่าของตัวแปร css

// get value of css variable
getComputedStyle(document.documentElement).getPropertyValue('--mobile-breakpoint'); // '642px'

// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];

// update media rule
mediaRule.media.mediaText = '..'


คำตอบยาว

ฉันเขียนสคริปต์เล็ก ๆ ซึ่งคุณสามารถรวมไว้ในเพจของคุณได้ แทนที่กฎสื่อทุกกฎด้วยค่าของ1pxตัวแปร css --replace-media-1pxกฎที่มีค่า2pxด้วย--replace-media-2pxและอื่น ๆ งานนี้สำหรับคำสั่งสื่อwith, min-width, max-width, height, min-heightและแม้ว่าพวกเขาจะเชื่อมต่อโดยใช้max-heightand

JavaScript:

function* visitCssRule(cssRule) {
    // visit imported stylesheet
    if (cssRule.type == cssRule.IMPORT_RULE)
        yield* visitStyleSheet(cssRule.styleSheet);

    // yield media rule
    if (cssRule.type == cssRule.MEDIA_RULE)
        yield cssRule;
}

function* visitStyleSheet(styleSheet) {
    try {
        // visit every rule in the stylesheet
        var cssRules = styleSheet.cssRules;
        for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
            yield* visitCssRule(cssRule);
    } catch (ignored) {}
}

function* findAllMediaRules() {
    // visit all stylesheets
    var styleSheets = document.styleSheets;
    for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
        yield* visitStyleSheet(styleSheet);
}

// collect all media rules
const mediaRules = Array.from(findAllMediaRules());

// read replacement values
var style = getComputedStyle(document.documentElement);
var replacements = [];
for (var k = 1, value; value = style.getPropertyValue('--replace-media-' + k + 'px'); k++)
    replacements.push(value);

// update media rules
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
    for (var k = 0; k < replacements.length; k++) {
        var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): ' + (k+1) + 'px\\)', 'g');
        var replacement = '($1: ' + replacements[k] + ')';
        mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
    }
}

CSS:

:root {
  --mobile-breakpoint: 642px;

  --replace-media-1px: var(--mobile-breakpoint);
  --replace-media-2px: ...;
}

@media (max-width: 1px) { /* replaced by 642px */
  ...
}

@media (max-width: 2px) {
  ...
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.