ฉันจะใช้ความทึบกับตัวแปรสี CSS ได้อย่างไร


169

ฉันกำลังออกแบบแอปด้วยอิเล็กตรอนดังนั้นฉันจึงสามารถเข้าถึงตัวแปร CSS ได้ ฉันได้กำหนดตัวแปรสีในvars.css:

:root {
  --color: #f0f0f0;
}

ฉันต้องการใช้สีนี้main.cssแต่มีการใช้ความทึบบางส่วน:

#element {
  background: (somehow use var(--color) at some opacity);
}

ฉันจะทำสิ่งนี้ได้อย่างไร ฉันไม่ได้ใช้ตัวประมวลผลล่วงหน้าใด ๆ มีเพียง CSS เท่านั้น ฉันต้องการคำตอบทั้งหมด CSS แต่ฉันจะยอมรับ JavaScript / jQuery

ฉันไม่สามารถใช้งานได้opacityเนื่องจากฉันใช้ภาพพื้นหลังที่ไม่ควรโปร่งใส


ดูเหมือนว่าคุณควรใช้มากกว่าหนึ่งองค์ประกอบ ....
epascarello

ฉันไม่ต้องการ แต่ดูเหมือนว่าฉันอาจจะต้อง ... :(
JoshyRobot

9
อ๊ากกกก !!!!! มันน่ารำคาญมาก! เกือบปี 2020 แล้ว ตัวเลือกสีได้รับสี #hex alpha / rgba ไม่ทำงานใน Sass / Stylus - เพราะไม่ใช่ค่า rgb ฉันควรใส่แถบเลื่อน 4 ตัวใน CMS สำหรับทุกๆสีหรือไม่
นายอำเภอ

คำตอบ:


282

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

อย่างไรก็ตามคุณสมบัติที่กำหนดเองช่วยให้คุณสามารถแปลงค่าฐานสิบหกของคุณเป็น RGB triplet เพื่อใช้กับrgba()เก็บค่านั้นในคุณสมบัติที่กำหนดเอง (รวมถึงเครื่องหมายจุลภาค!) แทนที่ค่านั้นโดยใช้var()ในrgba()ฟังก์ชันด้วยค่าอัลฟาที่คุณต้องการและมันจะ เพียงแค่ทำงาน:

:root {
  /* #f0f0f0 in decimal RGB */
  --color: 240, 240, 240;
}

body {
  color: #000;
  background-color: #000;
}

#element {
  background-color: rgba(var(--color), 0.8);
}
<p id="element">If you can see this, your browser supports custom properties.</p>

ดูเหมือนว่าเกือบจะดีเกินไปที่จะเป็นจริง 1มันทำงานอย่างไร?

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

ไวยากรณ์ที่อนุญาตสำหรับคุณสมบัติแบบกำหนดเองนั้นอนุญาตอย่างยิ่ง การผลิต <declaration-value> ตรงกับลำดับของโทเค็นอย่างน้อยหนึ่งรายการตราบใดที่ลำดับนั้นไม่มี <bad-string-token>, <bad-url-token>, ไม่ตรงกัน <) - โทเค็น>, <] - โทเค็น> หรือ <} - โทเค็น> หรือโทเค็น <semicolon-token> ระดับบนสุดหรือโทเค็น <delim-token> ที่มีค่า "!"

ตัวอย่างเช่นต่อไปนี้เป็นคุณสมบัติแบบกำหนดเองที่ถูกต้อง:

--foo: if(x > 5) this.width = 10;

แม้ว่าค่านี้จะไม่มีประโยชน์ในฐานะตัวแปรอย่างเห็นได้ชัดเนื่องจากค่านี้จะไม่ถูกต้องในคุณสมบัติปกติใด ๆ ก็ตาม แต่ JavaScript อาจอ่านและดำเนินการได้

และส่วนที่ 3 :

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

ซึ่งหมายความว่า240, 240, 240ค่าที่คุณเห็นด้านบนจะถูกแทนที่โดยตรงในrgba()ฟังก์ชันก่อนที่จะคำนวณการประกาศ ดังนั้นสิ่งนี้:

#element {
  background-color: rgba(var(--color), 0.8);
}

ซึ่งดูเหมือนจะไม่เป็น CSS ที่ถูกต้องในตอนแรกเนื่องจากrgba()คาดว่าจะมีค่าตัวเลขที่คั่นด้วยจุลภาคไม่น้อยกว่าสี่ค่ากลายเป็น:

#element {
  background-color: rgba(240, 240, 240, 0.8);
}

ซึ่งแน่นอนว่าเป็น CSS ที่ถูกต้องอย่างสมบูรณ์

ก้าวไปอีกขั้นคุณสามารถจัดเก็บองค์ประกอบอัลฟาในคุณสมบัติที่กำหนดเองได้:

:root {
  --color: 240, 240, 240;
  --alpha: 0.8;
}

และแทนที่ด้วยผลลัพธ์เดียวกัน:

#element {
  background-color: rgba(var(--color), var(--alpha));
}

สิ่งนี้ช่วยให้คุณมีค่าอัลฟาที่แตกต่างกันซึ่งคุณสามารถสลับไปมาได้ทันที


1 ก็คือถ้าคุณกำลังเรียกใช้ข้อมูลโค้ดในเบราว์เซอร์ที่ไม่รองรับคุณสมบัติที่กำหนดเอง


16
สวยมาก
roberrrt-s

2
@ Roberrrt: มันเป็นสิ่งที่ฉันควรตระหนักตั้งแต่เนิ่นๆอันที่จริงเมื่อฉันโพสต์คำตอบเหล่านี้ไป ก่อนหน้านี้
BoltClock

2
ถ้าเราจะใช้ตัวแปรนี้ทำไมไม่ใช้สิ่งที่ต้องการ: .element2 { background-color: rgba(var(--red), var(--low-opacity); }. ด้วยวิธีนี้คุณสามารถใช้ประโยชน์จากตัวแปรได้อย่างเต็มที่ :)
roberrrt-s

8
ขออภัยค่า"240, 240, 240"นี้ไม่สามารถแก้ไขได้ด้วยตัวเลือกสี นั่นเป็นสิ่งที่พลาดไม่ได้เมื่อคุณต้องหาสีที่เหมาะสมสำหรับ GUI ของคุณ
ฟรี

4
@ s3c: ข่าวดีก็คือ CSS Color 5 กำลังเปิดตัวฟังก์ชั่นใหม่ ๆ ที่น่าสนใจเพื่อจัดการกับค่าฐานสิบหกที่มีอยู่รวมถึงการเปลี่ยนช่องอัลฟา: drafts.csswg.org/css-color-5/#colormodify
BoltClock

21

ฉันรู้ว่า OP ไม่ได้ใช้ตัวประมวลผลล่วงหน้า แต่ฉันจะได้รับความช่วยเหลือหากข้อมูลต่อไปนี้เป็นส่วนหนึ่งของคำตอบที่นี่ (ฉันยังไม่สามารถแสดงความคิดเห็นมิฉะนั้นฉันจะแสดงความคิดเห็นคำตอบ @BoltClock

หากคุณกำลังใช้เช่น scss คำตอบข้างต้นจะล้มเหลวเนื่องจาก scss พยายามรวบรวมสไตล์ด้วยฟังก์ชัน rgba () / hsla () เฉพาะ scss ซึ่งต้องใช้ 4 พารามิเตอร์ อย่างไรก็ตาม rgba () / hsla () ยังเป็นฟังก์ชัน css ดั้งเดิมดังนั้นคุณสามารถใช้การแก้ไขสตริงเพื่อข้ามฟังก์ชัน scss

ตัวอย่าง (ใช้ได้ใน sass 3.5.0+):

:root {
    --color_rgb: 250, 250, 250;
    --color_hsl: 250, 50%, 50%;
}

div {
    /* This is valid CSS, but will fail in a scss compilation */
    background-color: rgba(var(--color_rgb), 0.5);
    
    /* This is valid scss, and will generate the CSS above */
    background-color: #{'rgba(var(--color_rgb), 0.5)'};
}
<div></div>

โปรดทราบว่าการแก้ไขสตริงจะใช้ไม่ได้กับฟังก์ชัน scss ที่ไม่ใช่ CSS เช่นlighten()เนื่องจากโค้ดผลลัพธ์จะไม่ใช่ CSS ที่ใช้งานได้ แม้ว่าจะยังคงเป็น scss ที่ถูกต้องดังนั้นคุณจะไม่ได้รับข้อผิดพลาดในการคอมไพล์


4
หากคุณต้องการใช้ฟังก์ชันสี CSS แบบเนทีฟในไฟล์ Sass .scss ของคุณคุณสามารถรวมคำจำกัดความของฟังก์ชันต่อไปนี้ไว้ที่ด้านบนของไฟล์เพื่อแทนที่การจัดการ Sass และทำให้ผ่าน: @function rgb($args...) { @return #{'rgb(#{$args})'}; } @function rgba($args...) { @return #{'rgba(#{$args})'}; } @function hsl($args...) { @return #{'hsl(#{$args})'}; } @function hsla($args...) { @return #{'hsla(#{$args})'}; }“ ``
lunelson

rgbaเป็นคำพ้องความหมายสำหรับrgbบางครั้งในขณะนี้ .. ดังนั้นคุณจึงได้รับอนุญาตให้วาง "a"
s3c

1
วิธีแก้ปัญหาอื่นสำหรับไฟล์ scss คือการใช้ตัวพิมพ์ใหญ่ ( RGB) ซึ่งถูกละเว้นโดย sass เช่น: color: RGB(var(--color_rgb), 0.5);. จากGitHub
Jono Job

คำตอบที่ดี! หากคุณกำหนดสีเป็นเลขฐานสิบหกแล้วคุณสามารถเพิ่มรหัสนี้เพื่อแปลงเป็นคุณสมบัติ rgb ที่กำหนดเองได้::root { @each $color, $value in $colors { --#{$color}_rgb: #{red($value), green($value), blue($value)}; } }
Torsten Kolb

13

ฉันอยู่ในสถานการณ์ที่คล้ายกัน แต่น่าเสียดายที่วิธีแก้ปัญหาที่ระบุไม่ได้ผลสำหรับฉันเนื่องจากตัวแปรอาจเป็นอะไรก็ได้จากrgbถึงhslเป็นhexหรือแม้แต่ชื่อสี
ฉันแก้ไขปัญหานี้ได้แล้วโดยใช้background-colorand the opacityกับ pseudo :afterหรือ:beforeelement:

.container {
    position: relative;
}

.container::before {
    content: "";
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    background-color: var(--color);
    opacity: 0.3;
}

รูปแบบอาจต้องเปลี่ยนแปลงเล็กน้อยขึ้นอยู่กับองค์ประกอบที่ควรใช้กับพื้นหลัง
นอกจากนี้อาจใช้ไม่ได้กับทุกสถานการณ์ แต่หวังว่าจะช่วยได้ในบางกรณีซึ่งไม่สามารถใช้โซลูชันอื่น

แก้ไข: ฉันเพิ่งสังเกตเห็นว่าโซลูชันนี้ส่งผลต่อสีข้อความอย่างเห็นได้ชัดเนื่องจากสร้างองค์ประกอบที่ด้านหน้าขององค์ประกอบเป้าหมายและใช้สีพื้นหลังโปร่งใสกับมัน
ซึ่งอาจเป็นปัญหาในบางกรณี


สิ่งนี้ไม่เพียง แต่มีข้อได้เปรียบในการอนุญาตข้อกำหนดของสีที่ยืดหยุ่นมากขึ้น (เช่นชื่อหรือrgbหรือHSL) แต่ยังช่วยหลีกเลี่ยงความขัดแย้งระหว่างฟังก์ชันสี CSS ดั้งเดิมกับฟังก์ชันสีของ Sass ดูคำตอบของ SimplyPhyด้านล่าง
Jim Ratliff

1
ผมคิดว่ามันจะดีกว่าที่จะใช้เพื่อให้คุณได้รับการสั่งซื้อที่เหมาะสมซ้อนโดยไม่ต้องเล่นกับ:before z-index
Mikko Rantalainen

5

นี้เป็นจริงที่เป็นไปได้ด้วย CSS มันสกปรกนิดหน่อยและคุณจะต้องใช้การไล่ระดับสี ฉันได้เขียนโค้ดตัวอย่างเล็ก ๆ ไว้เป็นตัวอย่างโปรดทราบว่าสำหรับพื้นหลังสีเข้มคุณควรใช้ความทึบสีดำสำหรับแสง - สีขาว:

:root {
  --red: rgba(255, 0, 0, 1);
  --white-low-opacity: rgba(255, 255, 255, .3);
  --white-high-opacity: rgba(255, 255, 255, .7);
  --black-low-opacity: rgba(0, 0, 0, .3);
  --black-high-opacity: rgba(0, 0, 0, .7);
}

div {
	width: 100px;
	height: 100px;
	margin: 10px;
}
    
    
.element1 {
	background: 
        linear-gradient(var(--white-low-opacity), var(--white-low-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}

.element2 {
	background: 
        linear-gradient(var(--white-high-opacity), var(--white-high-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}
    
.element3 {
	background: 
        linear-gradient(var(--black-low-opacity), var(--black-low-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}

.element4 {
	background: 
        linear-gradient(var(--black-high-opacity), var(--black-high-opacity)) no-repeat,
	linear-gradient(var(--red), var(--red)) no-repeat;
}
<div class="element1">hello world</div>
<div class="element2">hello world</div>
<div class="element3">hello world</div>
<div class="element4">hello world</div>


คุณไม่จำเป็นต้องระบุขนาดพื้นหลัง - การไล่ระดับสีไม่มีขนาดที่แท้จริงและจะยืดออกโดยอัตโนมัติ
BoltClock

@BoltClock ใช่ฉันคิดอย่างนั้นเมื่อฉันโพสต์มันเป็นเพียงการเล่นใน codepen;) ทำความสะอาดแล้วขอบคุณ!
roberrrt-s

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

มันใช้ไม่ได้จริงๆเมื่อพื้นหลังแตกต่างกัน แต่ตอนนี้ฉันถือว่าพื้นหลังเป็นสีขาว (255,255,255) เมื่อใช้ 'ความทึบ' อาจเป็นไปได้ว่าเป็นสีพื้นหลังหลักของ OP แต่แล้วอีกครั้งพื้นหลังสีขาวอาจจะพอดีกับความต้องการของสีที่อ่อนกว่าส่วนใหญ่เพื่อขยายที่ผู้คนจะไม่สังเกตเห็นสิ่งนี้
roberrrt-s

1
ฉันเพิ่งค้นพบอย่างอื่นที่ค่อนข้างเหลือเชื่อ ตอนนี้ฉันได้โพสต์คำตอบแล้ว
BoltClock

1
:root{
--color: 255, 0, 0;
}

#element{
    background-color: rgba(var(--color), opacity);
}

ที่คุณแทนที่ความทึบด้วยอะไรก็ได้ระหว่าง 0 ถึง 1


นี่เป็นความพยายามในการตอบคำถามหรือไม่? เพราะถ้าเป็นเช่นนั้นโค้ดก็ไม่สมเหตุสมผล โดยเฉพาะrgba(var(--color), opacity)บิต โดยเฉพาะอย่างยิ่งเนื่องจากค่าคุณสมบัติที่กำหนดเองของคุณคือสัญกรณ์ rgb () ทั้งหมด แต่ยังเป็นเพราะคีย์เวิร์ด "ทึบ"
BoltClock

woops ของฉันไม่ดีชิ้นส่วน rgb ไม่ควรอยู่ใน var
Pizza lord

1

SCSS / SASS

ข้อได้เปรียบ:คุณสามารถใช้ค่าสี Hex แทนเพื่อใช้ 8 บิตสำหรับทุกช่อง (0-255)

นี่คือวิธีที่ฉันทำด้วยแนวคิดเริ่มต้นของ: https://codyhouse.co/blog/post/how-to-combine-sass-color-functions-and-css-variables

แก้ไข:คุณสามารถแก้ไขฟังก์ชันอัลฟาเพื่อใช้#{$color-name}-rgbและละเว้นตัวแปร CSS * -r, * -g, * -b ที่สร้างขึ้น


ผลลัพธ์

body {
  --main-color: rgb(170, 68, 204);
  --main-color-rgb: 170,68,204;
  --main-color-r: 170;
  --main-color-g: 68;
  --main-color-b: 204;
}

.button-test {
  // Generated from the alpha function
  color: rgba(var(--main-color-r), var(--main-color-g), var(--main-color-b), 0.5);
  // OR (you wrote this yourself, see usage)
  color: rgba(var(--main-color-rgb), 0.5);
}

การใช้งาน:

body {
    @include defineColorRGB(--main-color, #aa44cc);
}

.button-test {
  // With alpha function:
  color: alpha(var(--main-color), 0.5);
  // OR just using the generated variable directly
  color: rgba(var(--main-color-rgb), 0.5);
}

Mixin และฟังก์ชั่น

@mixin defineColorRGB($color-name, $value) {
    $red: red($value);
    $green: green($value);
    $blue: blue($value);
    #{$color-name}: unquote("rgb(#{$red}, #{$green}, #{$blue})");
    #{$color-name}-rgb: $red,$green,$blue;
    #{$color-name}-r: $red;
    #{$color-name}-g: $green;
    #{$color-name}-b: $blue;
}

// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
@function str-replace($string, $search, $replace: '') {
    $index: str-index($string, $search);
    @if $index {
        @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
    }
    @return $string;
}

@function alpha($color, $opacity) {
    $color: str-replace($color, 'var(');
    $color: str-replace($color, ')');
    $color-r: var(#{$color+'-r'});
    $color-g: var(#{$color+'-g'});
    $color-b: var(#{$color+'-b'});
    @return rgba($color-r, $color-g, $color-b, $opacity);
}

หวังว่านี่จะช่วยใครบางคนได้บ้าง


1
ฉันชอบแนวทางนี้ ขอบคุณ
tonygatta

-1

คุณสามารถตั้งค่าตัวแปร / ค่าเฉพาะสำหรับแต่ละสี - สีดั้งเดิมและสีที่มีความทึบ:

:root {
  --color: #F00;
  --color-opacity: rgba(255, 0, 0, 0.5);
}
#a1 {
  background: var(--color);
} 
#a2 {
  background: var(--color-opacity);
}
<div id="a1">asdf</div>
<div id="a2">asdf</div>

หากคุณไม่สามารถใช้สิ่งนี้ได้และคุณพอใจกับโซลูชัน javascript คุณสามารถใช้อันนี้:

$(function() {
  $('button').click(function() {
    bgcolor = $('#a2').css('backgroundColor');
    rgb_value = bgcolor.match(/\d+,\s?\d+,\s?\d+/)[0]
    $('#a2').css('backgroundColor', 'rgba(' + rgb_value + ', 0.5)');
  });
});
:root {
  --color: #F00;
}
#a1 {
  background: var(--color);
} 
#a2 {
  background: var(--color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1">asdf</div>
<div id="a2">asdf</div>
<button>Click to change opacity</button>


1
ค่าความทึบจะเปลี่ยนไปดังนั้นการสร้างตัวแปรสำหรับทุกความทึบจึงน่ารำคาญ
JoshyRobot

-3

สำหรับการใช้ rgba () กับตัวแปร css ทั่วไปให้ลองทำดังนี้:

  1. ประกาศสีของคุณภายใน: รูท แต่อย่าใช้ rgb () เหมือนคำตอบอื่น ๆ เพียงแค่เขียนค่า

:root{
  --color : 255,0,0;
  }

  1. ใช้ตัวแปร --color โดยใช้ var () เป็นคำตอบอื่น ๆ

#some-element {
  color : rgba(var(--color),0.5);
}


-4

ใน CSS คุณควรจะใช้ค่า rgba ได้:

#element {
  background: rgba(240, 240, 240, 0.5);
}

หรือเพียงแค่ตั้งค่าความทึบ:

#element {
  background: #f0f0f0;
  opacity: 0.5;    
}

1
ฉันไม่สามารถฮาร์ดโค้ดค่า rgba ได้ฉันใช้ตัวแปรสี ฉันควรจะบอกว่าฉันไม่สามารถใช้ความทึบได้เพราะฉันจะมีภาพพื้นหลังที่ไม่ควรโปร่งใส
JoshyRobot

นี่ไม่ใช่วิธีแก้ b / c หากคุณต้องการให้ BG มีความโปร่งใสเท่านั้น แต่องค์ประกอบทั้งหมดมีความทึบจากนั้นการเพิ่มความทึบให้กับทุกสิ่งจะไม่เป็นประโยชน์
Levidps

-4

ถ้าคุณชอบสีฐานสิบหกเหมือนฉันมีวิธีอื่น ค่าฐานสิบหกคือ 6 หลักหลังจากนั้นคือค่าอัลฟา 00 คือความโปร่งใส 100% 99 คือประมาณ 75% จากนั้นใช้ตัวอักษร 'a1-af' แล้ว 'b1-bf' ที่ลงท้ายด้วย 'ff' ซึ่งทึบแสง 100%

:root {
--color: #F00;
}

#element {
background: var(--color)f6;
}

1
น่าเสียดายที่ฉันไม่คิดว่าจะได้ผล การรองรับรหัสเลขฐานสิบหก 8 หลักเริ่มแพร่กระจาย แต่ดูเหมือนว่าเคล็ดลับที่ใช้กับคำตอบที่ยอมรับจะไม่ได้ผลกับพวกเขา ตัวอย่าง: jsbin.com/nacuharige/edit?css,output
JoshyRobot

วิธีนี้ใช้ไม่ได้ผลแม้ว่าจะเป็นทางออกที่ดีหากเป็นเช่นนั้น
Braden Rockwell Napier
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.