마음의 안정을 찾기 위하여 - [JavaScript] HTML 페이지에서 배경색과 반대되는 보색으로 글씨 색상을 자동으로 지정하는 방법
2559425
398
572
관리자새글쓰기
태그위치로그방명록
별일없다의 생각
dawnsea's me2day/2010
색상(RGB)코드 추출기(Color...
Connection Generator/2010
최승호PD, '4대강 거짓말 검...
Green Monkey**/2010
Syng의 생각
syng's me2DAY/2010
천재 작곡가 윤일상이 기획,...
엘븐킹's Digital Factory/2010
[JavaScript] HTML 페이지에서 배경색과 반대되는 보색으로 글씨 색상을 자동으로 지정하는 방법
Web, Script/JavaScript | 2025/07/08 10:12

이 예제는 4가지 다른 방법으로 배경색과 대비되는 텍스트 색상을 자동으로 계산하는 방법을 보여줍니다:
주요 방법들:
1. 명도 기반 흑백 대비 (추천)

배경색의 명도를 계산하여 밝으면 검은색, 어두우면 흰색 사용
가장 실용적이고 가독성이 좋음

2. 색상환 보색

색상환에서 정확히 반대편 색상 계산
시각적으로 강한 대비, 디자인 강조에 적합

3. RGB 반전

각 RGB 값을 255에서 빼서 반전
구현이 간단하지만 회색 계열에서 대비 부족

4. WCAG 기준 대비

웹 접근성 가이드라인 기준으로 최적 대비 계산
접근성을 고려한 가장 권장되는 방법

색상 선택기를 사용하거나 "랜덤 색상" 버튼을 클릭하여 각 방법의 차이점을 실시간으로 확인할 수 있습니다. 일반적인 웹사이트에서는 방법 1(명도 기반) 또는 **방법 4(WCAG 기준)**를 사용하는 것이 좋습니다.



<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>자동 보색 텍스트 색상</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            transition: all 0.3s ease;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        
        .demo-section {
            margin: 20px 0;
            padding: 20px;
            border-radius: 8px;
            transition: all 0.3s ease;
        }
        
        .color-picker {
            margin: 10px 0;
        }
        
        .color-picker label {
            display: inline-block;
            width: 120px;
            font-weight: bold;
        }
        
        .color-picker input[type="color"] {
            width: 50px;
            height: 30px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        
        .method-title {
            font-size: 1.2em;
            font-weight: bold;
            margin-bottom: 10px;
            border-bottom: 2px solid;
            padding-bottom: 5px;
        }
        
        .explanation {
            margin: 10px 0;
            padding: 10px;
            background-color: rgba(255, 255, 255, 0.1);
            border-radius: 4px;
            font-size: 0.9em;
        }
        
        button {
            background-color: rgba(255, 255, 255, 0.2);
            border: 1px solid rgba(255, 255, 255, 0.3);
            color: inherit;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
            transition: all 0.3s ease;
        }
        
        button:hover {
            background-color: rgba(255, 255, 255, 0.3);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>자동 보색 텍스트 색상 지정</h1>
        
        <div class="color-picker">
            <label>배경색 선택:</label>
            <input type="color" id="bgColorPicker" value="#3498db">
            <button onclick="randomColor()">랜덤 색상</button>
        </div>
        
        <!-- 방법 1: 명도 기반 흑백 대비 -->
        <div class="demo-section" id="method1">
            <div class="method-title">방법 1: 명도 기반 흑백 대비</div>
            <div class="explanation">
                배경색의 명도를 계산하여 밝으면 검은색, 어두우면 흰색 텍스트를 사용합니다.
                가장 실용적이고 가독성이 좋은 방법입니다.
            </div>
            <p>이 텍스트는 명도 기반으로 자동 조정됩니다.</p>
            <button>버튼 예시</button>
        </div>
        
        <!-- 방법 2: 색상환 보색 -->
        <div class="demo-section" id="method2">
            <div class="method-title">방법 2: 색상환 보색</div>
            <div class="explanation">
                색상환에서 정확히 반대편에 위치한 보색을 계산합니다.
                시각적으로 강한 대비를 만들지만 가독성은 떨어질 수 있습니다.
            </div>
            <p>이 텍스트는 색상환 보색으로 설정됩니다.</p>
            <button>버튼 예시</button>
        </div>
        
        <!-- 방법 3: RGB 반전 -->
        <div class="demo-section" id="method3">
            <div class="method-title">방법 3: RGB 반전</div>
            <div class="explanation">
                각 RGB 값을 255에서 빼서 반전시킵니다.
                간단하지만 회색 계열에서는 대비가 약할 수 있습니다.
            </div>
            <p>이 텍스트는 RGB 반전으로 설정됩니다.</p>
            <button>버튼 예시</button>
        </div>
        
        <!-- 방법 4: 고급 대비 계산 -->
        <div class="demo-section" id="method4">
            <div class="method-title">방법 4: WCAG 기준 대비</div>
            <div class="explanation">
                WCAG(웹 접근성 가이드라인) 기준에 따라 최적의 대비를 계산합니다.
                접근성을 고려한 가장 권장되는 방법입니다.
            </div>
            <p>이 텍스트는 WCAG 기준으로 최적화됩니다.</p>
            <button>버튼 예시</button>
        </div>
        
        <div style="margin-top: 40px; padding: 20px; background-color: rgba(0,0,0,0.1); border-radius: 8px;">
            <h3>사용 권장사항:</h3>
            <ul>
                <li><strong>웹사이트 일반 텍스트:</strong> 방법 1 (명도 기반) 또는 방법 4 (WCAG 기준)</li>
                <li><strong>디자인 강조 요소:</strong> 방법 2 (색상환 보색)</li>
                <li><strong>간단한 구현:</strong> 방법 3 (RGB 반전)</li>
            </ul>
        </div>
    </div>

    <script>
        // 색상 변환 유틸리티 함수들
        function hexToRgb(hex) {
            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;
        }
        
        function rgbToHex(r, g, b) {
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }
        
        function rgbToHsl(r, g, b) {
            r /= 255; g /= 255; b /= 255;
            const max = Math.max(r, g, b), min = Math.min(r, g, b);
            let h, s, l = (max + min) / 2;
            
            if (max === min) {
                h = s = 0;
            } else {
                const d = max - min;
                s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
                switch (max) {
                    case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                    case g: h = (b - r) / d + 2; break;
                    case b: h = (r - g) / d + 4; break;
                }
                h /= 6;
            }
            return {h: h * 360, s: s * 100, l: l * 100};
        }
        
        function hslToRgb(h, s, l) {
            h /= 360; s /= 100; l /= 100;
            const hue2rgb = (p, q, t) => {
                if (t < 0) t += 1;
                if (t > 1) t -= 1;
                if (t < 1/6) return p + (q - p) * 6 * t;
                if (t < 1/2) return q;
                if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
                return p;
            };
            
            if (s === 0) {
                return {r: l * 255, g: l * 255, b: l * 255};
            }
            
            const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            const p = 2 * l - q;
            return {
                r: Math.round(hue2rgb(p, q, h + 1/3) * 255),
                g: Math.round(hue2rgb(p, q, h) * 255),
                b: Math.round(hue2rgb(p, q, h - 1/3) * 255)
            };
        }
        
        // 방법 1: 명도 기반 흑백 대비
        function getLuminanceContrastColor(bgColor) {
            const rgb = hexToRgb(bgColor);
            // 상대적 명도 계산 (ITU-R BT.709 표준)
            const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
            return luminance > 0.5 ? '#000000' : '#ffffff';
        }
        
        // 방법 2: 색상환 보색
        function getComplementaryColor(bgColor) {
            const rgb = hexToRgb(bgColor);
            const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
            const complementaryHue = (hsl.h + 180) % 360;
            const complementaryRgb = hslToRgb(complementaryHue, hsl.s, hsl.l);
            return rgbToHex(complementaryRgb.r, complementaryRgb.g, complementaryRgb.b);
        }
        
        // 방법 3: RGB 반전
        function getInvertedColor(bgColor) {
            const rgb = hexToRgb(bgColor);
            const invertedRgb = {
                r: 255 - rgb.r,
                g: 255 - rgb.g,
                b: 255 - rgb.b
            };
            return rgbToHex(invertedRgb.r, invertedRgb.g, invertedRgb.b);
        }
        
        // 방법 4: WCAG 기준 대비
        function getWCAGContrastColor(bgColor) {
            const rgb = hexToRgb(bgColor);
            
            // 상대적 명도 계산 (WCAG 기준)
            const getLuminance = (r, g, b) => {
                const [rs, gs, bs] = [r, g, b].map(c => {
                    c = c / 255;
                    return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
                });
                return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
            };
            
            const bgLuminance = getLuminance(rgb.r, rgb.g, rgb.b);
            const whiteContrast = (1 + 0.05) / (bgLuminance + 0.05);
            const blackContrast = (bgLuminance + 0.05) / (0 + 0.05);
            
            // 4.5:1 대비율 기준으로 판단
            return whiteContrast > blackContrast ? '#ffffff' : '#000000';
        }
        
        // 색상 적용 함수
        function applyColors(bgColor) {
            document.body.style.backgroundColor = bgColor;
            
            // 방법 1: 명도 기반
            const method1 = document.getElementById('method1');
            const luminanceColor = getLuminanceContrastColor(bgColor);
            method1.style.backgroundColor = bgColor;
            method1.style.color = luminanceColor;
            method1.style.borderColor = luminanceColor;
            
            // 방법 2: 색상환 보색
            const method2 = document.getElementById('method2');
            const complementaryColor = getComplementaryColor(bgColor);
            method2.style.backgroundColor = bgColor;
            method2.style.color = complementaryColor;
            method2.style.borderColor = complementaryColor;
            
            // 방법 3: RGB 반전
            const method3 = document.getElementById('method3');
            const invertedColor = getInvertedColor(bgColor);
            method3.style.backgroundColor = bgColor;
            method3.style.color = invertedColor;
            method3.style.borderColor = invertedColor;
            
            // 방법 4: WCAG 기준
            const method4 = document.getElementById('method4');
            const wcagColor = getWCAGContrastColor(bgColor);
            method4.style.backgroundColor = bgColor;
            method4.style.color = wcagColor;
            method4.style.borderColor = wcagColor;
            
            // 전체 텍스트 색상도 방법 1로 설정
            document.body.style.color = luminanceColor;
        }
        
        // 랜덤 색상 생성
        function randomColor() {
            const colors = ['#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#34495e', '#e67e22', '#95a5a6', '#7f8c8d'];
            const randomIndex = Math.floor(Math.random() * colors.length);
            const colorPicker = document.getElementById('bgColorPicker');
            colorPicker.value = colors[randomIndex];
            applyColors(colors[randomIndex]);
        }
        
        // 이벤트 리스너
        document.getElementById('bgColorPicker').addEventListener('input', function(e) {
            applyColors(e.target.value);
        });
        
        // 초기 색상 적용
        applyColors('#3498db');
    </script>
</body>
</html>

2025/07/08 10:12 2025/07/08 10:12
Article tag list Go to top
View Comment 0
Trackback URL :: 이 글에는 트랙백을 보낼 수 없습니다
 
 
 
 
PREV : [1][2][3][4][5] ... [1328] :
«   2025/07   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
전체 (1328)
출판 준비 (0)
My-Pro... (41)
사는 ... (933)
블로그... (22)
My Lib... (32)
게임 ... (23)
개발관... (3)
Smart ... (1)
Delphi (93)
C Builder (0)
Object... (0)
VC, MF... (10)
Window... (1)
Open API (3)
Visual... (0)
Java, JSP (2)
ASP.NET (0)
PHP (6)
Database (12)
리눅스 (29)
Windows (26)
Device... (1)
Embedded (1)
게임 ... (0)
Web Se... (2)
Web, S... (22)
잡다한... (7)
프로젝트 (0)
Personal (0)
대통령... (13)
Link (2)