덮힌 배경 영역의 밝기에 따라 텍스트 색상을 변경 하시겠습니까?


114

벌써 한동안 다음과 같은 생각을했기 때문에 이제 여러분의 의견과 가능한 해결책 등을 알고 싶습니다.

부모의 배경 이미지 또는 색상의 덮여 픽셀의 평균 밝기에 따라 텍스트의 색상을 변경하거나 미리 정의 된 이미지 / 아이콘 사이를 전환하는 플러그인 또는 기술을 찾고 있습니다.

배경의 가려진 영역이 다소 어둡다면 텍스트를 흰색으로 만들거나 아이콘을 전환하십시오.

또한 스크립트가 부모에 정의 된 배경색 또는 이미지가 없는지 확인한 다음 가장 가까운 (부모 요소에서 부모 요소까지) 계속 검색하면 좋을 것입니다.

이 아이디어에 대해 어떻게 생각하십니까? 이미 비슷한 것이 있습니까? 스크립트 예?

건배, J.


1
대답보다는 생각 일뿐입니다. HSL을 사용하여 색상을 설정 한 다음 밝기 값을 보는 방법이있을 수 있습니다. 해당 값이 특정 값보다 크면 CSS 규칙을 적용합니다.
Scott Brown

1
요소의 배경색을 R, G, B (및 선택적 알파) 값으로 파싱하여 알파 채널이 0으로 설정된 경우 DOM 트리를 작동 할 수 있습니다. 그러나 배경 이미지의 색상을 결정하는 것은 완전히 다른 문제입니다.
jackwanders


@Pascal 매우 유사하고 좋은 입력 ..하지만 내 질문에 대한 정확한 대답은 아닙니다.
James Cazzetta

답변:


175

이에 대한 흥미로운 리소스 :

다음은 W3C 알고리즘입니다 ( JSFiddle 데모 포함 ).

const rgb = [255, 0, 0];

// Randomly change to showcase updates
setInterval(setContrast, 1000);

function setContrast() {
  // Randomly update colours
  rgb[0] = Math.round(Math.random() * 255);
  rgb[1] = Math.round(Math.random() * 255);
  rgb[2] = Math.round(Math.random() * 255);

  // http://www.w3.org/TR/AERT#color-contrast
  const brightness = Math.round(((parseInt(rgb[0]) * 299) +
                      (parseInt(rgb[1]) * 587) +
                      (parseInt(rgb[2]) * 114)) / 1000);
  const textColour = (brightness > 125) ? 'black' : 'white';
  const backgroundColour = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
  $('#bg').css('color', textColour); 
  $('#bg').css('background-color', backgroundColour);
}
#bg {
  width: 200px;
  height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="bg">Text Example</div>


펠릭스 말이 맞아! 지금은 멀리 i'am하지만 돌아올 때 확실히, 나는 대답 업데이트됩니다
알렉스 볼

1
객체에 전달하면 다음과 같이 단락 될 수 있습니다. :::: const setContrast = rgb => (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000> 125? '화이트' '블랙'
누가 복음 로버트슨

css를 변경하기 위해 jquery가 필요합니까?
bluejayke

@bluejayke 아니, 다른 방법 ;-)있다
알렉스 볼

63

색상 대비 계산 에 대한 24 가지 방법에 대한이 기사 가 흥미로울 수 있습니다. 첫 번째 함수 세트가 잘못 되었기 때문에 무시하십시오. 그러나 YIQ 공식은 밝은 전경색을 사용할 것인지 어두운 전경색을 사용할 것인지 결정하는 데 도움이됩니다.

요소 (또는 조상)의 배경색을 얻은 후에는 기사에서이 함수를 사용하여 적합한 전경색을 결정할 수 있습니다.

function getContrastYIQ(hexcolor){
    hexcolor = hexcolor.replace("#", "");
    var r = parseInt(hexcolor.substr(0,2),16);
    var g = parseInt(hexcolor.substr(2,2),16);
    var b = parseInt(hexcolor.substr(4,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;
    return (yiq >= 128) ? 'black' : 'white';
}

고마워요, 이것은 정말 도움이됩니다 .. 이것은 설정된 배경색에 따라 다릅니다 ..하지만 루프처럼 각 픽셀을 실행하여 이미지의 평균 색상을 얻는 방법을 알고 있습니까?
James Cazzetta

4
es6에서는 다음과 같이 할 수 있습니다.const getContrastYIQ = hc => { const [r, g, b] = [0, 2, 4].map( p => parseInt( hc.substr( p, 2 ), 16 ) ); return ((r * 299) + (g * 587) + (b * 114)) / 1000 >= 128; }
Centril

이 함수를 가져 와서 약간 확장하여 항상 흑백이 아닌 두 가지 사용자 지정 색상을 반환 할 수 있습니다. 색상이 두 개가 가깝다면 여전히 대비 문제가 발생할 수 있지만 절대 색상을 반환하는 대신 좋은 대안입니다 jsfiddle.net/1905occv/1
Hanna

2
이것은 coo입니다. yiq를> = 160으로 조정하고 더 잘 작동했습니다.
Arturo

15

흥미로운 질문입니다. 내 즉각적인 생각은 배경색을 텍스트로 반전시키는 것이었다. 여기에는 단순히 배경을 구문 분석하고 RGB 값을 반전시키는 것이 포함됩니다.

이와 같은 것 : http://jsfiddle.net/2VTnZ/2/

var rgb = $('#test').css('backgroundColor');
var colors = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
var brightness = 1;

var r = colors[1];
var g = colors[2];
var b = colors[3];

var ir = Math.floor((255-r)*brightness);
var ig = Math.floor((255-g)*brightness);
var ib = Math.floor((255-b)*brightness);

$('#test').css('color', 'rgb('+ir+','+ig+','+ib+')');

반전 된 R, G, B 값을 평균화하고 서로 동일하게 설정하여 '반전 된'색상의 채도를 낮추고 싶을 것입니다. 그러나이 솔루션은 요소의 CSS 속성이 아닌 문자열에서 기본 색상을 가져옵니다. 신뢰할 수 있으려면 솔루션은 일반적으로 rgb () 또는 rgba () 값을 반환하는 배경색을 동적으로 얻어야하지만 브라우저에 따라 다를 수 있습니다.
jackwanders

예. 파싱을 쉽게하기 위해 16 진수 값을 사용했습니다. CSS에서 요소의 색상을 가져 오는 것을 포함하도록 바이올린을 업데이트했습니다. 바이올린을 업데이트하고 일종의 밝기 제어를 포함했습니다 (색상 수학에 대해 전혀 모르기 때문에 실제 밝기가 아닐 수 있습니다).
jeremyharris


2
배경색이 #808080!?
Nathan MacInnes

1
@NathanMacInnes 그것은 여전히 ​​그것을 뒤집을 것입니다. 스펙트럼 중간에서 무언가를 뒤집는 것이 그 자체로 결과를 낳을 것입니다. 이 코드는 색상을 반전 시키는데 한계가 있습니다.
jeremyharris

9

mix-blend-mode 트릭을 수행합니다.

header {
  overflow: hidden;
  height: 100vh;
  background: url(https://www.w3schools.com/html/pic_mountain.jpg) 50%/cover;
}

h2 {
  color: white;
  font: 900 35vmin/50vh arial;
  text-align: center;
  mix-blend-mode: difference;
  filter: drop-shadow(0.05em 0.05em orange);
}
<header>
  <h2 contentEditable role='textbox' aria-multiline='true' >Edit me here</h2>
</header>

추가 (2018 년 3 월) : 다음, 모든 다양한 유형의 모드 / 구현을 설명하는 멋진 튜토리얼 : https://css-tricks.com/css-techniques-and-effects-for-knockout-text/


5

BackgroundCheck 스크립트가 매우 유용하다는 것을 알았습니다 .

배경의 전체 밝기 (배경 이미지 또는 색상)를 감지하고 배경의 밝기에 따라 할당 된 텍스트 요소 ( background--light또는 background--dark)에 클래스를 적용합니다 .

정지 및 움직이는 요소에 적용 할 수 있습니다.

( 출처 )


기여해 주셔서 감사합니다!
James Cazzetta 2015 년

배경색에서도 작동합니까? 나는 스크립트를 빨리 읽었고 배경색을 사용하여 밝기를 확인하는 것을 볼 수 없습니다. 이미지 만.
Jørgen Skår Fischer 2015 년

1
요르겐 안녕하세요, 저는 colourBrightness 스크립트는 당신의 목적을 제공 할 수 있습니다 생각 : github.com/jamiebrittain/colourBrightness.js이
cptstarling

5

ES6를 사용하는 경우 16 진수를 RGB로 변환 한 다음 다음을 사용할 수 있습니다.

const hexToRgb = hex => {
    // turn hex val to RGB
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
    return result
        ? {
              r: parseInt(result[1], 16),
              g: parseInt(result[2], 16),
              b: parseInt(result[3], 16)
          }
        : null
}

// calc to work out if it will match on black or white better
const setContrast = rgb =>
    (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 > 125 ? 'black' : 'white'

const getCorrectColor = setContrast(hexToRgb(#ffffff))

4

내 시도는 다음과 같습니다.

(function ($) {
    $.fn.contrastingText = function () {
        var el = this,
            transparent;
        transparent = function (c) {
            var m = c.match(/[0-9]+/g);
            if (m !== null) {
                return !!m[3];
            }
            else return false;
        };
        while (transparent(el.css('background-color'))) {
            el = el.parent();
        }
        var parts = el.css('background-color').match(/[0-9]+/g);
        this.lightBackground = !!Math.round(
            (
                parseInt(parts[0], 10) + // red
                parseInt(parts[1], 10) + // green
                parseInt(parts[2], 10) // blue
            ) / 765 // 255 * 3, so that we avg, then normalize to 1
        );
        if (this.lightBackground) {
            this.css('color', 'black');
        } else {
            this.css('color', 'white');
        }
        return this;
    };
}(jQuery));

그런 다음 사용하려면 :

var t = $('#my-el');
t.contrastingText();

이것은 즉시 텍스트를 검정색 또는 흰색으로 적절하게 만듭니다. 아이콘을 수행하려면 :

if (t.lightBackground) {
    iconSuffix = 'black';
} else {
    iconSuffix = 'white';
}

그러면 각 아이콘이 'save' + iconSuffix + '.jpg'.

컨테이너가 부모를 오버플로하는 경우에는 작동하지 않습니다 (예 : CSS 높이가 0이고 오버플로가 숨겨지지 않은 경우). 그 작업을 수행하는 것은 훨씬 더 복잡 할 것입니다.


1

[@ alex-ball, @jeremyharris] 답변을 결합하여 이것이 저에게 가장 좋은 방법이라는 것을 알았습니다.

        $('.elzahaby-bg').each(function () {
            var rgb = $(this).css('backgroundColor');
            var colors = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

            var r = colors[1];
            var g = colors[2];
            var b = colors[3];

            var o = Math.round(((parseInt(r) * 299) + (parseInt(g) * 587) + (parseInt(b) * 114)) /1000);

            if(o > 125) {
                $(this).css('color', 'black');
            }else{
                $(this).css('color', 'white');
            }
        });
*{
    padding: 9px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class='elzahaby-bg' style='background-color:#000'>color is white</div>

<div class='elzahaby-bg' style='background-color:#fff'>color is black</div>
<div class='elzahaby-bg' style='background-color:yellow'>color is black</div>
<div class='elzahaby-bg' style='background-color:red'>color is white</div>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.