<div class="wrapper">
  <div class="element">
    <h2>💃🏻💃🏻RGBA 👈 👉 HSLA 🕺🏻 🕺🏻</h2>
    <div class="form">
      <div class="control">
        <label for="rgba">RGBA:</label>
        <input type="text" id="rgba" name="rgba" value="rgba(120,144,250,.5)" />
        <span class="help" id="rgbaError">✅👍🏽</span>
      </div>
      <div class="control">
        <label for="hsla">HSLA:</label>
        <input type="text" name="hex" id="hsla" value="hsla(229, 93%, 73%, .5)" />
        <span class="help" id="hslaError">✅👍</span>
      </div>
    </div>
  </div>
</div>
@import url("https://fonts.googleapis.com/css?family=Gochi+Hand");

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  margin: 0;
  padding: 0;
  background-color: #291642;
  font-family: "Gochi Hand", sans-serif;
  color: #fff;
  font-size: 130%;
  letter-spacing: 0.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  width: 100vw;
  min-height: 100vh;
  padding: 10px;
}

.wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  margin: 3vh 0;
}

.element {
  padding: 4vh;
  min-width: 50vw;
  min-height: 30vh;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
  border-radius: 8px;
  font-size: 3rem;
  color: #a3afaa;
}

h2 {
  margin: 4vh;
  font-size: 2rem;
  color: #fff;
  text-shadow: 2px 2px 1px var(--color);
}

.form {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5vh;
  font-size: 1.5rem;
}

.control {
  display: grid;
  gap: 1vh;
  grid-template-columns: auto 1fr auto;
}

span,
label {
  align-self: center;
  color: #fff;
  text-shadow: 2px 2px 1px var(--color);
}

input {
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 3px;
  width: 100%;
  color: #2c3e50;
  font-family: "Gochi Hand", sans-serif;
}

.error input {
  border-color: red;
  color: red;
}

:root {
  --color: rgba(120, 144, 250, 0.5);
}

body {
  background-color: var(--color);
  transition: all 0.2s ease;
}

.wrapper {
  background-image: radial-gradient(circle at center, var(--color), #291642),
    linear-gradient(to bottom, #291642, #291642);
  background-repeat: no-repeat;
  background-position: center;
  background-clip: padding-box;
  border-radius: 8px;
  background-blend-mode: multiply, screen;
}
View Compiled
const hsla = document.getElementById("hsla");
const rgba = document.getElementById("rgba");

/**
 * Check the Hsla Function
 * @param {string} hsl - <hsl-color>, eg, #rgb | #rrggbb | #rgba | #rrggbbaa
 */

function checkHsla(hsla) {
  const hslaRegex = /^hsla\(((((([12]?[1-9]?\d)|[12]0\d|(3[0-5]\d))(\.\d+)?)|(\.\d+))(deg)?|(0|0?\.\d+)turn|(([0-6](\.\d+)?)|(\.\d+))rad)(((,\s?(([1-9]?\d(\.\d+)?)|100|(\.\d+))%){2},\s?)|((\s(([1-9]?\d(\.\d+)?)|100|(\.\d+))%){2}\s\/\s))((0?\.\d+)|[01]|(([1-9]?\d(\.\d+)?)|100|(\.\d+))%)\)$/i;

  if (hslaRegex.test(hsla)) {
    return true;
  }
}

/**
 * Check the RGB Function
 * @param {string} rgb - <rgb-color>, eg, rgb(r g b) | rgb(r g b / a) | rgb(r, g, b, a) | rgba(r g b / a)
 */

function checkRgba(rgba) {
  const rgbaRegex = /^rgba\((((((((1?[1-9]?\d)|10\d|(2[0-4]\d)|25[0-5]),\s?)){3})|(((([1-9]?\d(\.\d+)?)|100|(\.\d+))%,\s?){3}))|(((((1?[1-9]?\d)|10\d|(2[0-4]\d)|25[0-5])\s){3})|(((([1-9]?\d(\.\d+)?)|100|(\.\d+))%\s){3}))\/\s)((0?\.\d+)|[01]|(([1-9]?\d(\.\d+)?)|100|(\.\d+))%)\)$/i;

  if (rgbaRegex.test(rgba)) {
    return true;
  }
}

/**
 * RGBA 颜色转 HSLA颜色函数
 * @param {string} rgba - <rgba-color>
 */
function RGBAToHSLA(rgba) {
  let sep = rgba.indexOf(",") > -1 ? "," : " ";
  rgba = rgba.substr(5).split(")")[0].split(sep);

  if (rgba.indexOf("/") > -1) {
    rgba.splice(3, 1);
  }

  for (let R in rgba) {
    let r = rgba[R];
    if (r.indexOf("%") > -1) {
      let p = r.substr(0, r.length - 1) / 100;

      if (R < 3) {
        rgba[R] = Math.round(p * 255);
      } else {
        rgba[R] = p;
      }
    }
  }

  // 颜色的红、绿和蓝坐标,它们的值是在0 ~ 1之间的实数
  let r = rgba[0] / 255;
  let g = rgba[1] / 255;
  let b = rgba[2] / 255;
  let a = rgba[3];

  // 找出最大值和最小值,并计算出它们之间的差值
  let M = Math.max(r, g, b); // 最大值
  let m = Math.min(r, g, b); // 最小值
  let delta = M - m; // 最大值 M 和最小值 m 之间的差值

  // 初始值HSL的通道h, s, l初始值为0
  let h = 0,
    s = 0,
    l = 0;

  // 计算色相h

  // 如果C = 0 即 M = m, 没有差别,这个时候h=0
  if (delta == 0) {
    h = 0;
  } else if (M == r) {
    // r = M (红色通道r是最大值)
    // M = r ❯❯❯ H' = ((g - b) / C) % 6
    h = ((g - b) / delta) % 6;
  } else if (M == g) {
    // g = M (绿色通道g是最大值)
    // M = g ❯❯❯ H' = ((b - r) / C) + 2
    h = (b - r) / delta + 2;
  } else {
    // b = M (蓝色通道b是最大值)
    // M = b ❯❯❯ H' = ((r - g) / C) + 4
    h = (r - g) / delta + 4;
  }

  // 最终色相的值 H = H' x 60°
  h = Math.round(h * 60);

  // 计算出来的色相值h,如果小于0的话,需要做一下处理
  if (h < 0) {
    h += 360;
  }

  // 计算亮度l
  l = (M + m) / 2;

  // 计算饱和度
  s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));

  // 将s和l转换成百分比值
  s = +(s * 100).toFixed(0);
  l = +(l * 100).toFixed(0);

  return `hsla(${h},${s}%,${l}%,${a})`;
}

/**
 * HSLA 颜色转换成RGBA颜色 函数
 * @param {string} hsla - <hsla-color>
 */
function HSLAToRGBA(hsla) {
  let sep = hsla.indexOf(",") > -1 ? "," : " ";
  hsla = hsla.substr(5).split(")")[0].split(sep);

  if (hsla.indexOf("/") > -1) {
    hsla.splice(3, 1);
  }

  let h = hsla[0];
  // let s = hsl[1].substr(0, hsl[1].length - 1) / 100;
  let s = hsla[1].replace("%", "") / 100;
  // let l = hsl[2].substr(0, hsl[2].length - 1) / 100;
  let l = hsla[2].replace("%", "") / 100;
  let a = hsla[3];

  if (h.indexOf("deg") > -1) {
    h = h.replace("deg", "");
  } else if (h.indexOf("rad") > -1) {
    h = Math.round(h.replace("rad", "") * (180 / Math.PI));
  } else if (h.indexOf("turn") > -1) {
    h = Math.round(h.replace("turn", "") * 360);
  }

  if (h > 360) {
    h %= 360;
  }

  // 计算色度c的值
  // ❯❯❯ C = (1 - | 2l - 1 |) * s
  let c = (1 - Math.abs(2 * l - 1)) * s;

  // 计算x值,用作中间值
  // ❯❯❯ X = C * (1 - | H' mod 2 - 1 |)
  // ❯❯❯ H' = H / 60 ❯❯❯ C * (1 - | (H / 60) mod 2 - 1 |)
  let x = c * (1 - Math.abs(((h / 60) % 2) - 1));

  // 计算m值,用于调整亮度值
  // ❯❯❯ m = L - C / 2
  let m = l - c / 2;

  // 初始化r, g, b的值为0
  let r = 0,
    g = 0,
    b = 0;

  // 根据色相h的颜色区域,计算出r, g, b的值
  if (0 <= h && h < 60) {
    // ❯❯❯ R' = C, G' = X, B' = 0
    r = c;
    g = x;
    b = 0;
  } else if (60 <= h && h < 120) {
    // ❯❯❯ R' = X, G' = C, B' = 0
    r = x;
    g = c;
    b = 0;
  } else if (120 <= h && h < 180) {
    // ❯❯❯ R' = 0, G' = C, B' = X
    r = 0;
    g = c;
    b = x;
  } else if (180 <= h && h < 240) {
    // ❯❯❯ R' = 0, G' = X, B' = C
    r = 0;
    g = x;
    b = c;
  } else if (240 <= h && h < 300) {
    // ❯❯❯ R' = X, G' = 0, B' = C
    r = x;
    g = 0;
    b = c;
  } else if (300 <= h && h < 360) {
    // ❯❯❯ R' = C, G' = 0, B' = X
    r = c;
    g = 0;
    b = x;
  }

  // 计算出最终的R、G、B通道的值
  // 每个通道加上m值,然后乘以255,再将值作四舍五入
  // ❯❯❯ R = (R' + m) * 255
  // ❯❯❯ G = (G' + m) * 255
  // ❯❯❯ B = (B' + m) * 255
  r = Math.round((r + m) * 255);
  g = Math.round((g + m) * 255);
  b = Math.round((b + m) * 255);

  // 输出RGB颜色:rgb(r g b) || rgb(r, g, b)
  return `rgba(${r},${g},${b},${a})`;
}

hsla.addEventListener("change", function () {
  let color = hsla.value;
  if (checkHsla(color)) {
    rgba.value = HSLAToRGBA(color);
    document.documentElement.style.setProperty("--color", color);
    hsla.parentNode.classList.remove("error");
  } else {
    hsla.parentNode.classList.add("error");
    document.getElementById("hslaError").textContent = "❎👎🏽";
  }
});

rgba.addEventListener("change", function () {
  let color = rgba.value;
  if (checkRgba(color)) {
    hsla.value = RGBAToHSLA(color);
    document.documentElement.style.setProperty("--color", color);
    rgba.parentNode.classList.remove("error");
  } else {
    rgba.parentNode.classList.add("error");
    document.getElementById("rgbError").textContent = "❎👎🏽";
  }
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.