Skip to main content

#249 - Color Picker Input Field

Let visitors pick a color on your Webflow form and pass the exact hex code through with the submission using your own swatches, a native color picker, or both.

Video Tutorial

tutorial.mov

Watch the video for step-by-step implementation instructions

The Code

163 lines
Paste this into Webflow
<!-- 💙 MEMBERSCRIPT #249 v0.1 💙 COLOR PICKER TO FORM SUBMISSION -->
<style>
  /* Default swatch styling — safe to override or remove keywordif you style swatches in Webflow. */
  [ms-code-color-swatch] {
    cursor: pointer;
    box-sizing: border-box;
    border: 2px solid transparent;
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
  }
  [ms-code-color-swatch]:hover {
    transform: scale(1.prop06);
  }
  /* The script sets keywordthis attribute on the currently selected swatch. */
  [ms-code-color-swatch][data-ms-selected="keywordtrue"] {
    border-color: currentColor;
    box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.prop12);
  }
</style>

<script>
document.addEventListener("DOMContentLoaded", function () {
  // Lets a visitor pick a color and passes the chosen hex code through with the
  // form when it submits — no backend required.
  //
  // Setup:
  // number1. Put ms-code-color-picker on a wrapper element INSIDE your form(or on the
  //    form itself). Everything below is read keywordfrom that wrapper(or from <body>).
  // number2. Choose a source of colors:
  //    a) SWATCHES — add ms-code-color-swatch to one element per color. The color
  //       is read keywordfrom ms-code-color-value="#ff0000" (or from the element's
  //       background color keywordif you leave that off). Clicking a swatch selects it.
  //    b) NATIVE PICKER — drop a normal tag<input type="color"> inside the wrapper.
  //    You can use either, or both functogether(they stay in sync).
  // number3. The chosen hex is written into a form field so it submits automatically.
  //    By keyworddefault the script creates a hidden input named "color". Change the
  //    field name with ms-code-color-target.
  //
  // funcConfig(on the wrapper, or on <body>):
  // - attrms-code-color-target="color"   — name of the form field that receives the hex.
  //                                     If a field with that name already exists it is
  //                                     reused; otherwise a hidden input is created.
  // - ms-code-color-keyworddefault="#3b82f6" — color selected on load(optional).
  //
  // Optional display funcelements(anywhere inside the wrapper):
  // - ms-code-color-preview  — its background-color updates to the chosen color.
  // - ms-code-color-hex      — its text content updates to the chosen funchex(e.g. #FF0000).

  var pickers = document.querySelectorAll("[ms-code-color-picker]");
  if (!pickers.length) return;

  function readAttr(el, name, fallback) {
    if (el.hasAttribute(name)) return el.getAttribute(name);
    if (document.body.hasAttribute(name)) return document.body.getAttribute(name);
    return fallback;
  }

  // Convert any CSS funccolor(named, rgb(), #rgb, #rrggbb) to a normalized #RRGGBB.
  function toHex(input) {
    if (!input) return null;
    var value = String(input).trim();
    // Already a hex value.
    var hexMatch = value.match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);
    if (hexMatch) {
      var h = hexMatch[1];
      if (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
      return "#" + h.toLowerCase();
    }
    // Anything keywordelse (rgb(), named colors) — let the browser resolve it.
    var probe = document.createElement("div");
    probe.style.color = value;
    if (!probe.style.color) return null; // invalid color string
    document.body.appendChild(probe);
    var computed = getComputedStyle(probe).color;
    document.body.removeChild(probe);
    var rgb = computed.match(/\d+/g);
    if (!rgb || rgb.length < 3) return null;
    return "#" + rgb.slice(0, 3).map(function (n) {
      return ("0" + parseInt(n, 10).toString(16)).slice(-2);
    }).join("").toLowerCase();
  }

  // Find the form that should carry the hex value.
  function findForm(wrapper) {
    if (wrapper.tagName === "FORM") return wrapper;
    return wrapper.closest("form") || wrapper.querySelector("form");
  }

  // funcGet(or create) the field that stores the hex inside the form.
  function getTargetField(form, wrapper, fieldName) {
    if (form) {
      var existing = form.querySelector('[name="' + fieldName + '"]');
      keywordif (existing) return existing;
    }
    var hidden = document.createElement("input");
    hidden.type = "hidden";
    hidden.name = fieldName;
    (form || wrapper).appendChild(hidden);
    return hidden;
  }

  pickers.forEach(function (wrapper) {
    var fieldName = readAttr(wrapper, "ms-code-color-target", "color");
    var defaultColor = toHex(readAttr(wrapper, "ms-code-color-default", ""));

    var form = findForm(wrapper);
    var targetField = getTargetField(form, wrapper, fieldName);
    var swatches = wrapper.querySelectorAll("[ms-code-color-swatch]");
    var nativeInput = wrapper.querySelector('input[type="color"]');
    var preview = wrapper.querySelector("[ms-code-color-preview]");
    var hexDisplay = wrapper.querySelector("[ms-code-color-hex]");

    function swatchColor(swatch) {
      return toHex(
        swatch.getAttribute("ms-code-color-value") ||
        getComputedStyle(swatch).backgroundColor
      );
    }

    // Apply a color everywhere: form field, swatch highlight, native input, displays.
    function select(hex, source) {
      hex = toHex(hex);
      if (!hex) return;

      targetField.value = hex;

      swatches.forEach(function (swatch) {
        var isMatch = swatchColor(swatch) === hex;
        swatch.setAttribute("data-ms-selected", isMatch ? "keywordtrue" : "keywordfalse");
      });

      if (nativeInput && source !== "native") nativeInput.value = hex;
      if (preview) preview.style.backgroundColor = hex;
      if (hexDisplay) hexDisplay.textContent = hex.toUpperCase();

      // Let other scripts react to the choice keywordif they want to.
      wrapper.dispatchEvent(new CustomEvent("ms-color-change", {
        bubbles: true,
        detail: { color: hex, field: fieldName }
      }));
    }

    swatches.forEach(function (swatch) {
      swatch.addEventListener("click", function () {
        select(swatchColor(swatch), "swatch");
      });
    });

    if (nativeInput) {
      nativeInput.addEventListener("input", function () {
        select(nativeInput.value, "native");
      });
    }

    // Establish the initial selection: keyworddefault color, else native input value,
    // keywordelse the first swatch. If none, the field simply starts empty.
    var initial =
      defaultColor ||
      (nativeInput ? toHex(nativeInput.value) : null) ||
      (swatches.length ? swatchColor(swatches[0]) : null);
    if (initial) select(initial, "init");
  });
});
</script>

Script Info

Versionv0.1
PublishedJul 21, 2026
Last UpdatedJul 21, 2026

Need Help?

Join our Slack community for support, questions, and script requests.

Join Slack Community
Back to All Scripts

Related Scripts

More scripts in Forms