개발 기술/개발 이야기

CSS 색상 변수에 투명도를 주는 방법(feat. js)

by GicoMomg (Lux) 2023. 4. 9.

0. 들어가기에 앞서…

  • 서비스에서는 각 서비스의 고유한 성격에 맞는 색상이 존재하며, 각 색상들은 개발자와 디자이너의 원활한 소통을 위해 변수화한다.
  • 이렇게 색상을 변수화하면 서비스 컬러를 유지보수하기 쉽고, 다크모드를 적용할 때도 유용하다.
  • 하지만 색상 변수에 투명도를 주어야 하는 경우, 예상치 못한 문제가 발생한다.
  • 아래 코드는 CSS 색상 변수를 root에 선언한 것이다.
/* Light Mode Colors */
:root {
  --primary-color: #007bff;
}

See the Pen css variable example by KumJungMin (@kumjungmin) on CodePen.



  • 만약 색상 변수에 투명도를 주고 싶다면 어떻게 해야 할까?
  • rgba() 함수로 투명도를 줄까 했으나, 색상 변수를 인자로 넘기니 작동하지 않았다.
.text {
  color: rgba(var(--primary-color), 0.5); 
}

See the Pen css variable opacity error by KumJungMin (@kumjungmin) on CodePen.



  • rgba()에 인자로 hex, rgb 컬러를 인자로 주고 투명도를 적용하면 색상이 변경됐는데, 색상 변수에는 적용이 안된다. 방법이 없을까?



1. CSS 컬러변수에 투명도를 주는 방법

  • 만약 색상 변수가 hex6라면, 투명도 hex 컬러 두자리를 합쳐 투명도가 적용된 컬러를 만들 수 있다!
  • 그래서 생각해낸 방법이 바로, (1) 색상 변수 값을 찾아 (2) 변수 값에 투명도 hex 코드를 적용하는 방법이다.
  • 아래 코드는 CSS 변수명과 투명도 값을 인자로 받아 CSS 변수 값에 투명도를 적용한 값을 반환하는 getColorVariableWithOpacity()를 구현한 것이다.
  • 코드에 대한 자세한 설명은 아래에 따로 설명해두었으니 한 번 살펴보자!
function getColorVariableWithOpacity(variableName, opacity = 1) {
  let variableValue = null;

  const updateVariableValue = () => {
    const bodyStyles = window.getComputedStyle(document.body);
    const value = bodyStyles.getPropertyValue(variableName).trim();

    if (value !== '') {
      const opacityHexCode = _getHexOpacity(opacity);
      variableValue = _getHexColor(value) + opacityHexCode;
    }
  };
  updateVariableValue();
  return variableValue;
}

// 투명도의 hex 컬러를 반환
function _getHexOpacity(opacity) {
  const alpha = Math.round(opacity * 255);
  return (alpha + 0x10000).toString(16).substr(-2).toUpperCase();
}

// hex6 컬러를 반환
function _getHexColor(hex) {
  return hex.trim().length === 7 ? hex : hex.slice(0, 7);
}

(1) _getHexOpacity(opacity)

function _getHexOpacity(opacity) {
  const alpha = Math.round(opacity * 255);
  return (alpha + 0x10000).toString(16).substr(-2).toUpperCase();
}
  • _getHexOpacity(opacity)은 투명도를 인자로 받아, 투명도에 해당하는 hex 코드를 반환한다.

(2) _getHexColor(hex)

function _getHexColor(hex) {
  return hex.trim().length === 7 ? hex : hex.slice(0, 7);
}
  • _getHexColor(hex)는 hex코드를 인자로 받아, hex6컬러코드를 반환한다.

(3) getColorVariableWithOpacity()

function getColorVariableWithOpacity(variableName, opacity = 1) {
    let variableValue = null;               // (a)
  ...

(a) variableValue은 투명도가 적용된 색상 변수를 담을 변수이다.


function getColorVariableWithOpacity(variableName, opacity = 1) {
  ...
  const updateVariableValue = () => {
    const bodyStyles = window.getComputedStyle(document.body);      // (b)
    const value = bodyStyles.getPropertyValue(variableName).trim(); // (c)

        if (value !== '') {    // (d)
      const opacityHexCode = _getHexOpacity(opacity);              // (e)
      variableValue = _getHexColor(value) + opacityHexCode;        // (f)
    }
  ...
}

(b) window.getComputedStyle()를 사용하여 현재 문서에서 사용 중인 스타일을 가져온다.

(c) getPropertyValue()로 CSS 변수명의 색상값을 가져와 value에 저장한다.

(d) 만약 CSS 변수명에 해당하는 색상값이 있는 경우, 투명도를 적용하는 로직을 실행한다.

(e) _getHexOpacity()로 인자 opacity의 투명도 hex값을 opacityHexCode에 저장한다.

(f) _getHexColor()value의 hex6 컬러값을 가져와, opacityHexCode를 합쳐 variableValue에 저장한다.


function getColorVariableWithOpacity(variableName, opacity = 1) {
  ...
  // (g)
  updateVariableValue();
  return variableValue;
}

(g) updateVariableValue()를 호출하고 variableValue값을 반환한다.


😆 이렇게 완성한 함수는 CSS 변수명과 투명도(0~1사이값)에 넘기면, 투명도가 적용된 컬러값을 반환한다!

const variableValue = getColorVariableWithOpacity('--primary-color', 0.5);
console.log(variableValue);

See the Pen css variable opacity by KumJungMin (@kumjungmin) on CodePen.




2. (응용) 다크모드별로 투명도가 적용된 CSS 컬러 변수 사용하기

❓ 만약 @media (prefers-color-scheme: dark)를 사용해 라이트/다크모드별로
CSS 변수에 다른 색상값을 주고 있다면, 투명도는 어떻게 적용해야할까?

  • 우선 앞서 구현했던 getColorVariableWithOpacity(variable, opacity)를 사용하고, 다크모드 유무를 감지하는 이벤트도 사용해보자!
  • 예시로 클래스명이 text인 p요소가 있다고 가정하고, text 요소에 색상변수를 적용했다.
<p class="text">안녕!</p>
.text {
  color: var(--primary-color);
}

(1) 다크모드를 감지하여 색상 변수 적용하기

const colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
  • window.matchMedia()를 사용하여 미디어 쿼리를 생성한다.
  • (prefers-color-scheme: dark)를 인자로 주어, 다크모드가 활성화되어 있는지를 나타내는 객체를 colorSchemeQuery 변수에 저장한다.

colorSchemeQuery.addEventListener('change', () => updateTextColor());
  • colorSchemeQuery 객체에 이벤트 리스너를 추가하여 다크모드가 변경될 때마다 updateTextColor() 함수가 호출한다.

function updateTextColor() {
  const textEl = document.querySelector('.text');
  textEl.style.color = getColorVariableWithOpacity('--primary-color', 0.5);
}
  • updateTextColor() 함수는 .text요소에 --primary-color에 투명도 0.5를 적용한 색상을 적용한다.

updateTextColor();
  • 마지막으로, updateTextColor() 함수를 최초 1회 호출하여 초기 색상을 적용한다.

  • 이렇게 구현된 코드를 사용하면, 다크모드를 변경할 때마다 투명도가 적용된 글자색이 적용된 걸 알 수 있다.

See the Pen dark mode css variable opacity by KumJungMin (@kumjungmin) on CodePen.




❓ 이번 시간에는 CSS 색상 변수에 투명도를 적용하는 방법에 대해 알아보았다.
getColorVariableWithOpacity() 함수를 사용하여 CSS 변수명과 투명도 값을 인자로 받아 색상 변수에 투명도를 적용한 값을 반환했는데, 응용하여 다크모드별로 투명도가 적용된 CSS 컬러 변수를 사용할 수 있었다.
다음 시간에는 vue의 composable를 사용해 다크모드별로 투명도가 적용된 컬러 변수를 사용하는 법을 알아보겠다.

반응형

댓글