Làm cách nào để áp dụng độ mờ cho biến màu CSS?


144

Tôi đang thiết kế một ứng dụng bằng điện tử, vì vậy tôi có quyền truy cập vào các biến CSS. Tôi đã xác định một biến màu trong vars.css:

:root {
  --color: #f0f0f0;
}

Tôi muốn sử dụng màu này main.css, nhưng với một số độ mờ được áp dụng:

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

Tôi sẽ đi đâu để tới đó? Tôi không sử dụng bất kỳ bộ tiền xử lý nào, chỉ CSS. Tôi muốn một câu trả lời toàn CSS, nhưng tôi sẽ chấp nhận JavaScript / jQuery.

Tôi không thể sử dụng opacityvì tôi đang sử dụng hình nền không trong suốt.


Vì vậy, có vẻ như bạn nên sử dụng nhiều hơn một yếu tố ....
eprebello

Tôi không muốn, nhưng có vẻ như tôi có thể phải ... :(
JoshyRobot

3
AHHHHH !!!!! Điều này thật khó chịu! Bây giờ là gần 2020 rồi. Bộ chọn màu được #hex màu. alpha / rgba không hoạt động trong Sass / Stylus - vì đó không phải là giá trị rgb. Tôi có nên đặt 4 thanh trượt trong CMS của mình cho mỗi màu không?
sheriffderek

Câu trả lời:


240

Bạn không thể lấy một giá trị màu hiện có và áp dụng kênh alpha cho nó. Cụ thể, bạn không thể lấy một giá trị hex hiện có, chẳng hạn như #f0f0f0, cung cấp cho nó một thành phần alpha và sử dụng giá trị kết quả với một thuộc tính khác.

Tuy nhiên, các thuộc tính tùy chỉnh cho phép bạn chuyển đổi giá trị hex của mình thành bộ ba RGB để sử dụng rgba(), lưu trữ giá trị đó trong thuộc tính tùy chỉnh (bao gồm dấu phẩy!), Thay thế giá trị đó bằng var()một rgba()hàm bằng giá trị alpha mong muốn của bạn và nó sẽ chỉ làm việc

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

Điều này dường như quá tốt để trở thành sự thật. 1 Nó hoạt động như thế nào?

Điều kỳ diệu nằm ở chỗ các giá trị của các thuộc tính tùy chỉnh được thay thế như khi thay thế các var()tham chiếu trong một giá trị thuộc tính, trước khi giá trị của thuộc tính đó được tính toán. Điều này có nghĩa là liên quan đến các thuộc tính tùy chỉnh, giá trị --colortrong ví dụ của bạn hoàn toàn không phải là giá trị màu cho đến khi một var(--color)biểu thức xuất hiện ở đâu đó có giá trị màu (và chỉ trong ngữ cảnh đó). Từ phần 2.1 của thông số css-biến:

Cú pháp được phép cho các thuộc tính tùy chỉnh là rất dễ dàng. Việc sản xuất <kê khai-giá trị> khớp với bất kỳ chuỗi nào của một hoặc nhiều mã thông báo, miễn là chuỗi đó không chứa <bad-string-token>, <bad-url-token>, chưa từng có <) - mã thông báo>, <] - mã thông báo> hoặc <} - mã thông báo> hoặc mã thông báo <semicolon-token> cấp cao nhất hoặc mã thông báo <delim-token> có giá trị "!".

Ví dụ: dưới đây là một thuộc tính tùy chỉnh hợp lệ:

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

Mặc dù giá trị này rõ ràng là vô dụng như một biến, vì nó sẽ không hợp lệ trong bất kỳ thuộc tính thông thường nào, nó có thể được đọc và hành động bằng JavaScript.

phần 3 :

Nếu một thuộc tính chứa một hoặc nhiều hàm var () và các hàm đó có hiệu lực về mặt cú pháp, thì ngữ pháp của toàn bộ thuộc tính phải được coi là hợp lệ tại thời điểm phân tích. Nó chỉ được kiểm tra cú pháp tại thời điểm giá trị được tính toán, sau khi các hàm var () đã được thay thế.

Điều này có nghĩa là 240, 240, 240giá trị bạn thấy ở trên được thay thế trực tiếp vào rgba()hàm trước khi khai báo được tính toán. Vậy đây:

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

lúc đầu dường như không phải là CSS hợp lệ vì rgba()hy vọng không ít hơn bốn giá trị số được phân tách bằng dấu phẩy, sẽ trở thành:

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

trong đó, tất nhiên, là CSS hoàn toàn hợp lệ.

Tiến thêm một bước nữa, bạn có thể lưu trữ thành phần alpha trong thuộc tính tùy chỉnh của riêng mình:

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

và thay thế nó, với cùng một kết quả:

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

Điều này cho phép bạn có các giá trị alpha khác nhau mà bạn có thể trao đổi khi đang di chuyển.


1 Vâng, đó là, nếu bạn đang chạy đoạn mã trong trình duyệt không hỗ trợ các thuộc tính tùy chỉnh.


12
Điều này thật đẹp
roberrrt-s

1
@Roberrrt: Đó là điều mà lẽ ra tôi nên nhận ra sớm, trên thực tế, khi tôi đăng những câu trả lời này trước đây.
BoltClock

2
Nếu chúng ta đang đi var này, tại sao không sử dụng cái gì đó như : .element2 { background-color: rgba(var(--red), var(--low-opacity); }. Bằng cách này bạn hoàn toàn có thể sử dụng các biến sử dụng :).
roberrrt-s

7
Thật không may, giá trị "240, 240, 240"không thể chỉnh sửa với bộ chọn màu. Đó là một thiếu sót lớn khi bạn cần tìm màu sắc phù hợp cho GUI của mình.
GetFree

1
@ s3c Cú pháp var(--hex-color)99được chuyển đổi thành hai mã thông báo #333333 99(chú ý khoảng trống để phân tách mã thông báo) rõ ràng không phải là thứ bạn muốn. Thuộc tính tùy chỉnh ban đầu được xác định để sao chép mã thông báo, không phải chuỗi và đây là kết quả cuối cùng. Bây giờ là quá muộn để khắc phục điều này.
Mikko Rantalainen

19

Tôi biết OP không sử dụng bộ tiền xử lý, nhưng tôi sẽ được giúp đỡ nếu thông tin sau đây là một phần của câu trả lời ở đây (tôi chưa thể nhận xét, nếu không tôi sẽ nhận xét câu trả lời @BoltClock.

Nếu bạn đang sử dụng, ví dụ scss, câu trả lời ở trên sẽ thất bại, vì scss cố gắng biên dịch các kiểu với hàm rgba () / hsla () dành riêng cho scss, yêu cầu 4 tham số. Tuy nhiên, rgba () / hsla () cũng là các hàm css riêng, vì vậy bạn có thể sử dụng phép nội suy chuỗi để bỏ qua hàm scss.

Ví dụ (hợp lệ trong 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>

Lưu ý rằng phép nội suy chuỗi sẽ không hoạt động đối với các hàm scss không phải CSS, chẳng hạn như lighten(), vì mã kết quả sẽ không phải là CSS chức năng. Nó vẫn sẽ là scss hợp lệ, vì vậy bạn sẽ không nhận được lỗi trong quá trình biên dịch.


4
Nếu bạn thích sử dụng chức năng màu CSS có nguồn gốc trong các tập tin của bạn Sass .scss, bạn có thể bao gồm các định nghĩa hàm sau ở phía trên cùng của tập tin của bạn để ghi đè Sass' xử lý và làm cho họ đi qua: @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

rgbalà một từ đồng nghĩa trong rgbmột thời gian khá lâu .. Do đó, bạn được phép bỏ "a".
s3c

1
Một cách giải quyết khác cho các tệp scss là sử dụng chữ hoa ( RGB) mà sau đó bị bỏ qua bởi sass. Vd : color: RGB(var(--color_rgb), 0.5);. Từ GitHub
Jono Job

9

Tôi đang ở trong một tình huống tương tự, nhưng tiếc là giải pháp cho không làm việc cho tôi, như các biến có thể là bất cứ điều gì từ rgbđể hslđến hexhoặc thậm chí tên màu.
Tôi giải quyết vấn đề này ngay bây giờ, bằng cách áp dụng background-coloropacityđến một giả :afterhoặc :beforeyếu tố:

.container {
    position: relative;
}

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

Các kiểu có thể cần phải thay đổi một chút, tùy thuộc vào yếu tố nền nên được áp dụng.
Ngoài ra, nó có thể không hoạt động cho tất cả các tình huống, nhưng hy vọng nó sẽ giúp ích trong một số trường hợp, trong đó các giải pháp khác không thể được sử dụng.

Chỉnh sửa: Tôi chỉ nhận thấy rằng giải pháp này rõ ràng cũng tác động đến màu văn bản, vì nó tạo ra một yếu tố trước phần tử đích và áp dụng màu nền trong suốt cho nó.
Đây có thể là một vấn đề trong một số trường hợp.


Điều này không chỉ có lợi thế là cho phép đặc tả linh hoạt hơn về màu sắc (ví dụ: tên hoặc rgbhoặc HSL) mà còn tránh mọi xung đột giữa các chức năng màu CSS gốc và chức năng màu của Sass. Xem câu trả lời của SimplyPhy bên dưới.
Jim Ratliff

1
Tôi nghĩ rằng tốt hơn để sử dụng :befoređể bạn có được thứ tự sắp xếp đúng mà không cần chơi với z-index.
Mikko Rantalainen

5

Điều này thực sự có thể với CSS . Nó chỉ hơi bẩn một chút và bạn sẽ phải sử dụng độ dốc. Tôi đã mã hóa một đoạn nhỏ làm ví dụ, lưu ý rằng đối với nền tối, bạn nên sử dụng độ mờ màu đen, như đối với ánh sáng - màu trắng:

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


Bạn không cần chỉ định kích thước nền - độ dốc không có kích thước nội tại và kết quả sẽ tự động kéo dài.
BoltClock

@BoltClock Vâng, tôi thực sự nghĩ về điều đó khi tôi đăng nó, nó chỉ là một chút chơi xung quanh trong codepen;). Dọn dẹp ngay bây giờ, cảm ơn!
roberrrt-s

Điều này thật thông minh, tôi đã không nghĩ đến việc xếp lớp gradient màu đặc với nhau khi tôi trả lời một câu hỏi tương tự năm ngoái. Câu hỏi này có lẽ là khái quát hơn dù sao nó được viết, câu tôi trả lời là cho một trường hợp sử dụng rất cụ thể.
BoltClock

Mặc dù vậy, nó không thực sự hoạt động khi các nền khác nhau, bây giờ tôi giả sử nền trắng (255,255,255) khi áp dụng 'độ mờ'. Nó có thể có thể được mặc định là màu nền chính của OP. Nhưng một lần nữa, nền trắng có thể sẽ phù hợp với nhu cầu của hầu hết các màu nhạt hơn cho phần mở rộng mà mọi người sẽ không nhận thấy điều này.
roberrrt-s

1
Tôi mới phát hiện ra một thứ khác thật khó tin. Bây giờ tôi đã đăng một câu trả lời.
BoltClock

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

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

nơi bạn thay thế độ mờ bằng bất cứ thứ gì từ 0 đến 1


Đây có phải là một nỗ lực để trả lời câu hỏi? Bởi vì nếu vậy, mã không thực sự có ý nghĩa. Đặc biệt là rgba(var(--color), opacity)bit. Đặc biệt vì giá trị thuộc tính tùy chỉnh của bạn là toàn bộ ký hiệu rgb (). Nhưng cũng vì từ khóa "opacity".
BoltClock

làm xấu đi những phần rgb của tôi không nên có trong var
Pizza Lord

1

SCSS / SASS

Ưu điểm: Bạn chỉ có thể sử dụng các giá trị màu Hex, thay vào đó để sử dụng 8 Bit cho mỗi kênh (0-255).

Đây là cách tôi đã thực hiện với ý tưởng ban đầu về: https://codyhouse.co/blog/post/how-to-combine-sass-color-fifts-and-css-variables

Chỉnh sửa: Bạn cũng có thể sửa đổi hàm alpha để chỉ sử dụng #{$color-name}-rgbvà bỏ qua các biến CSS * -r, * -g, * -b.


Kết quả

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

Sử dụng:

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 và các chức năng

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

Hy vọng điều này sẽ giúp ai đó tiết kiệm thời gian.


1
Tôi thích cách tiếp cận này. Cảm ơn
tonygatta

0

Bạn có thể đặt biến / giá trị cụ thể cho từng màu - bản gốc và màu có độ mờ:

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

Nếu bạn không thể sử dụng cái này và bạn ổn với giải pháp javascript, bạn có thể sử dụng cái này:

$(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
Giá trị độ mờ sẽ thay đổi, vì vậy sẽ rất khó chịu khi tạo một biến cho mọi độ mờ.
JoshyRobot

-1

Để sử dụng rgba () với biến css chung, hãy thử điều này:

  1. Khai báo màu của bạn bên trong: root, nhưng không sử dụng rgb () như các câu trả lời khác làm. chỉ viết giá trị

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

  1. Sử dụng biến --color bằng var () như các câu trả lời khác

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


-3

Trong CSS, bạn có thể sử dụng các giá trị rgba:

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

hoặc chỉ đặt độ mờ:

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

1
Tôi không thể mã hóa giá trị rgba, tôi đang sử dụng các biến màu. Tôi nên đề cập rằng tôi không thể sử dụng độ mờ vì tôi sẽ có một hình nền không nên trong suốt.
JoshyRobot

Đây không phải là giải pháp b / c nếu bạn chỉ muốn BG có độ trong suốt nhưng yếu tố đầy đủ có độ mờ sau đó thêm độ mờ cho mọi thứ không hữu ích.
Levidps

-4

Nếu bạn yêu thích màu hex như tôi thì có một giải pháp khác. Giá trị hex là 6 chữ số sau đó là giá trị alpha. 00 là 100% trong suốt 99 là khoảng 75% sau đó nó sử dụng bảng chữ cái 'a1-af' rồi 'b1-bf' kết thúc bằng 'ff' mờ 100%.

:root {
--color: #F00;
}

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

1
Thật không may, tôi không nghĩ rằng điều này làm việc. Hỗ trợ mã hex 8 chữ số đang bắt đầu lan rộng, nhưng có vẻ như thủ thuật được sử dụng với câu trả lời được chấp nhận hoạt động với chúng. Ví dụ: jsbin.com/nacuharige/edit?css,output
JoshyRobot

Điều này không hoạt động, mặc dù nó sẽ là một giải pháp tuyệt vời nếu nó đã làm.
Braden Rockwell Napier
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.