One way is to simply assign the text, or value, of the <option>
elements as a CSS custom property of the <div>
elements you're creating, and then take advantage of CSS generated content to create the colour swatch, for example:
// here we use CSS.setProperty to set the property-value of
// the --colour custom property to the value contained within
// the <option> element over which we're iterating:
c.style.setProperty('--colour', selElmnt.options[j].value);
And, in the CSS:
/* we style the <div> elements using CSS Grid,
although flex would work perfectly well */
.select-items > div {
display: grid;
grid-template-areas: "colour colourName";
grid-template-columns: 1em max-content;
/* here we set a gap between 'swatch' and the
text-content: */
grid-gap: 0.5em;
/* setting padding to enforce spacing between
elements above and below: */
padding: 0.2em 0;
}
/* creating the pseudo-elements: */
.select-items > div::before {
content: '';
/* here we set the background-color of the current
pseudo-element to the value held in the --colour
custom property: */
background-color: var(--colour);
/* and place the pseudo-element in the named
grid-area: */
grid-area: colour;
}
The notable caveat with this approach, though, is that the property-value held in the <option>
element's value
attribute must be a valid CSS value, as the following demonstration illustrates (note the lack of a colour swatch for both the colours prefixed with 'pale' and the 'purple' colour, which for some reason has the value of 'mauve'):
var x, i, j, selElmnt, a, b, c;
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
selElmnt = x[i].getElementsByTagName("select")[0];
a = document.createElement("DIV");
a.setAttribute("class", "select-selected");
a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
x[i].appendChild(a);
b = document.createElement("DIV");
b.setAttribute("class", "select-items select-hide");
for (j = 1; j < selElmnt.length; j++) {
c = document.createElement("DIV");
c.innerHTML = selElmnt.options[j].innerHTML;
c.style.setProperty('--colour', selElmnt.options[j].value);
c.addEventListener("click", function(e) {
var y, i, k, s, h;
s = this.parentNode.parentNode.getElementsByTagName("select")[0];
h = this.parentNode.previousSibling;
for (i = 0; i < s.length; i++) {
if (s.options[i].innerHTML == this.innerHTML) {
s.selectedIndex = i;
h.innerHTML = this.innerHTML;
y = this.parentNode.getElementsByClassName("same-as-selected");
for (k = 0; k < y.length; k++) {
y[k].removeAttribute("class");
}
this.setAttribute("class", "same-as-selected");
break;
}
}
h.click();
});
b.appendChild(c);
}
x[i].appendChild(b);
a.addEventListener("click", function(e) {
e.stopPropagation();
closeAllSelect(this);
this.nextSibling.classList.toggle("select-hide");
this.classList.toggle("select-arrow-active");
});
}
function closeAllSelect(elmnt) {
var x, y, i, arrNo = [];
x = document.getElementsByClassName("select-items");
y = document.getElementsByClassName("select-selected");
for (i = 0; i < y.length; i++) {
if (elmnt == y[i]) {
arrNo.push(i)
} else {
y[i].classList.remove("select-arrow-active");
}
}
for (i = 0; i < x.length; i++) {
if (arrNo.indexOf(i)) {
x[i].classList.add("select-hide");
}
}
}
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none;
}
.select-selected {
background-color: #FFFFFF;
}
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #717171 transparent transparent transparent;
}
.select-selected.select-arrow-active:after {
border-color: transparent transparent #717171 transparent;
top: 7px;
}
.select-selected {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 6px 12px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 10px 16px;
line-height: 1.6;
border: 0.5px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
position: absolute;
background-color: White;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
.select-items>div {
display: grid;
grid-template-areas: "colour colourName";
grid-template-columns: 1em max-content;
grid-gap: 0.5em;
padding: 0.2em 0;
}
.select-items>div::before {
content: '';
background-color: var(--colour);
grid-area: colour;
}
.select-hide {
display: none;
}
.select-items div:hover,
.same-as-selected {
background-color: rgba(246, 245, 245, 0.9);
}
.myButton {
background-color: #286BEF;
border-radius: 6px;
border: 1px solid #ffffff;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial;
font-weight: 550;
font-size: 13px;
padding: 12px 23px;
text-decoration: none;
position: absolute;
left: 280px;
}
.myButton:hover {
background-color: #0688fa;
}
.myButton:relative {
top: 10px;
}
* {
box-sizing: border-box;
}
.column {
float: left;
width: 40%;
padding: 10px;
}
.row:after {
content: "";
display: table;
clear: both;
}
p {
color: #494848;
font-family: Arial;
font-size: 13px;
}
<div class="row">
<div class="column">
<p>Notes</p>
</div>
<div class="column">
<div class="custom-select" style="width:200px;">
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="RED">Red</option>
<option value="GREEN">Green</option>
<option value="BLUE">Blue</option>
<option value="ORANGE">Orange</option>
<option value="YELLOW">Yellow</option>
<option value="MAUVE">Purple</option>
<option value="PALE_GREEN">Pale green</option>
<option value="PALE_RED">Pale red</option>
<option value="PALE_BLUE">Pale blue</option>
<option value="CYAN">Cyan</option>
<option value="GRAY">Grey</option>
</select>
</div>
</div>
</div>
<br>
<a href="#" class="myButton">Submit</a>
To rectify that, the easiest solution would be to modify those values in some way, either using different – recognised HTML – colour-names in the value
attribute, or using some other colour notation, such as rgb()
/rgba()
, hsl()
/hsla()
or hexadecimal.
Using updated HTML colour names, for example:
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="RED">Red</option>
<option value="GREEN">Green</option>
<option value="BLUE">Blue</option>
<option value="ORANGE">Orange</option>
<option value="YELLOW">Yellow</option>
<option value="PURPLE">Purple</option>
<option value="PALEGREEN">Pale green</option>
<option value="LIGHTCORAL">Pale red</option>
<option value="PALETURQUOISE">Pale blue</option>
<option value="CYAN">Cyan</option>
<option value="GRAY">Grey</option>
</select>
var x, i, j, selElmnt, a, b, c;
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
selElmnt = x[i].getElementsByTagName("select")[0];
a = document.createElement("DIV");
a.setAttribute("class", "select-selected");
a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
x[i].appendChild(a);
b = document.createElement("DIV");
b.setAttribute("class", "select-items select-hide");
for (j = 1; j < selElmnt.length; j++) {
c = document.createElement("DIV");
c.innerHTML = selElmnt.options[j].innerHTML;
c.style.setProperty('--colour', selElmnt.options[j].value);
c.addEventListener("click", function(e) {
var y, i, k, s, h;
s = this.parentNode.parentNode.getElementsByTagName("select")[0];
h = this.parentNode.previousSibling;
for (i = 0; i < s.length; i++) {
if (s.options[i].innerHTML == this.innerHTML) {
s.selectedIndex = i;
h.innerHTML = this.innerHTML;
y = this.parentNode.getElementsByClassName("same-as-selected");
for (k = 0; k < y.length; k++) {
y[k].removeAttribute("class");
}
this.setAttribute("class", "same-as-selected");
break;
}
}
h.click();
});
b.appendChild(c);
}
x[i].appendChild(b);
a.addEventListener("click", function(e) {
e.stopPropagation();
closeAllSelect(this);
this.nextSibling.classList.toggle("select-hide");
this.classList.toggle("select-arrow-active");
});
}
function closeAllSelect(elmnt) {
/* A function that will close all select boxes in the document,
except the current select box: */
var x, y, i, arrNo = [];
x = document.getElementsByClassName("select-items");
y = document.getElementsByClassName("select-selected");
for (i = 0; i < y.length; i++) {
if (elmnt == y[i]) {
arrNo.push(i)
} else {
y[i].classList.remove("select-arrow-active");
}
}
for (i = 0; i < x.length; i++) {
if (arrNo.indexOf(i)) {
x[i].classList.add("select-hide");
}
}
}
document.addEventListener("click", closeAllSelect);
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none;
}
.select-selected {
background-color: #FFFFFF;
}
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #717171 transparent transparent transparent;
}
.select-selected.select-arrow-active:after {
border-color: transparent transparent #717171 transparent;
top: 7px;
}
.select-selected {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 6px 12px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 10px 16px;
line-height: 1.6;
border: 0.5px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
position: absolute;
background-color: White;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
.select-items>div {
display: grid;
grid-template-areas: "colour colourName";
grid-template-columns: 1em max-content;
grid-gap: 0.5em;
padding: 0.2em 0;
}
.select-items>div::before {
content: '';
background-color: var(--colour);
grid-area: colour;
}
.select-hide {
display: none;
}
.select-items div:hover,
.same-as-selected {
background-color: rgba(246, 245, 245, 0.9);
}
.myButton {
background-color: #286BEF;
border-radius: 6px;
border: 1px solid #ffffff;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial;
font-weight: 550;
font-size: 13px;
padding: 12px 23px;
text-decoration: none;
position: absolute;
left: 280px;
}
.myButton:hover {
background-color: #0688fa;
}
.myButton:relative {
top: 10px;
}
* {
box-sizing: border-box;
}
.column {
float: left;
width: 40%;
padding: 10px;
}
.row:after {
content: "";
display: table;
clear: both;
}
p {
color: #494848;
font-family: Arial;
font-size: 13px;
}
<div class="row">
<div class="column">
<p>Notes</p>
</div>
<div class="column">
<div class="custom-select" style="width:200px;">
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="RED">Red</option>
<option value="GREEN">Green</option>
<option value="BLUE">Blue</option>
<option value="ORANGE">Orange</option>
<option value="YELLOW">Yellow</option>
<option value="PURPLE">Purple</option>
<option value="PALEGREEN">Pale green</option>
<option value="LIGHTCORAL">Pale red</option>
<option value="PALETURQUOISE">Pale blue</option>
<option value="CYAN">Cyan</option>
<option value="GRAY">Grey</option>
</select>
</div>
</div>
</div>
<br>
<a href="#" class="myButton">Submit</a>
Updated hex values:
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="#f00">Red</option>
<option value="#0f0">Green</option>
<option value="#00f">Blue</option>
<option value="#fa0">Orange</option>
<option value="#ff0">Yellow</option>
<option value="#808">Purple</option>
<option value="#90fb98">Pale green</option>
<option value="#f08080">Pale red</option>
<option value="#aee">Pale blue</option>
<option value="#0ff">Cyan</option>
<option value="#808080">Grey</option>
</select>
var x, i, j, selElmnt, a, b, c;
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
selElmnt = x[i].getElementsByTagName("select")[0];
a = document.createElement("DIV");
a.setAttribute("class", "select-selected");
a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
x[i].appendChild(a);
b = document.createElement("DIV");
b.setAttribute("class", "select-items select-hide");
for (j = 1; j < selElmnt.length; j++) {
c = document.createElement("DIV");
c.innerHTML = selElmnt.options[j].innerHTML;
c.style.setProperty('--colour', selElmnt.options[j].value);
c.addEventListener("click", function(e) {
var y, i, k, s, h;
s = this.parentNode.parentNode.getElementsByTagName("select")[0];
h = this.parentNode.previousSibling;
for (i = 0; i < s.length; i++) {
if (s.options[i].innerHTML == this.innerHTML) {
s.selectedIndex = i;
h.innerHTML = this.innerHTML;
y = this.parentNode.getElementsByClassName("same-as-selected");
for (k = 0; k < y.length; k++) {
y[k].removeAttribute("class");
}
this.setAttribute("class", "same-as-selected");
break;
}
}
h.click();
});
b.appendChild(c);
}
x[i].appendChild(b);
a.addEventListener("click", function(e) {
e.stopPropagation();
closeAllSelect(this);
this.nextSibling.classList.toggle("select-hide");
this.classList.toggle("select-arrow-active");
});
}
function closeAllSelect(elmnt) {
var x, y, i, arrNo = [];
x = document.getElementsByClassName("select-items");
y = document.getElementsByClassName("select-selected");
for (i = 0; i < y.length; i++) {
if (elmnt == y[i]) {
arrNo.push(i)
} else {
y[i].classList.remove("select-arrow-active");
}
}
for (i = 0; i < x.length; i++) {
if (arrNo.indexOf(i)) {
x[i].classList.add("select-hide");
}
}
}
document.addEventListener("click", closeAllSelect);
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none;
}
.select-selected {
background-color: #FFFFFF;
}
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #717171 transparent transparent transparent;
}
.select-selected.select-arrow-active:after {
border-color: transparent transparent #717171 transparent;
top: 7px;
}
.select-selected {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 6px 12px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 10px 16px;
line-height: 1.6;
border: 0.5px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
position: absolute;
background-color: White;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
.select-items>div {
display: grid;
grid-template-areas: "colour colourName";
grid-template-columns: 1em max-content;
grid-gap: 0.5em;
padding: 0.2em 0;
}
.select-items>div::before {
content: '';
background-color: var(--colour);
grid-area: colour;
}
.select-hide {
display: none;
}
.select-items div:hover,
.same-as-selected {
background-color: rgba(246, 245, 245, 0.9);
}
.myButton {
background-color: #286BEF;
border-radius: 6px;
border: 1px solid #ffffff;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial;
font-weight: 550;
font-size: 13px;
padding: 12px 23px;
text-decoration: none;
position: absolute;
left: 280px;
}
.myButton:hover {
background-color: #0688fa;
}
.myButton:relative {
top: 10px;
}
* {
box-sizing: border-box;
}
.column {
float: left;
width: 40%;
padding: 10px;
}
.row:after {
content: "";
display: table;
clear: both;
}
p {
color: #494848;
font-family: Arial;
font-size: 13px;
}
<div class="row">
<div class="column">
<p>Notes</p>
</div>
<div class="column">
<div class="custom-select" style="width:200px;">
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="#f00">Red</option>
<option value="#0f0">Green</option>
<option value="#00f">Blue</option>
<option value="#fa0">Orange</option>
<option value="#ff0">Yellow</option>
<option value="#808">Purple</option>
<option value="#90fb98">Pale green</option>
<option value="#f08080">Pale red</option>
<option value="#aee">Pale blue</option>
<option value="#0ff">Cyan</option>
<option value="#808080">Grey</option>
</select>
</div>
</div>
</div>
<br>
<a href="#" class="myButton">Submit</a>
Obviously modifying the value
attribute risks adverse effects on what you're doing with those values – inserting into a database or integrating with another API for example – so, rather than updating the value
attribute it may be preferred to introduce a custom data-*
attribute to hold the representation of the desired colour:
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="RED" data-swatch="red">Red</option>
<option value="GREEN" data-swatch="green">Green</option>
<option value="BLUE" data-swatch="blue">Blue</option>
<option value="ORANGE" data-swatch="orange">Orange</option>
<option value="YELLOW" data-swatch="yellow">Yellow</option>
<option value="MAUVE" data-swatch="purple">Purple</option>
<option value="PALE_GREEN" data-swatch="palegreen">Pale green</option>
<option value="PALE_RED" data-swatch="lightcoral">Pale red</option>
<option value="PALE_BLUE" data-swatch="paleturquoise">Pale blue</option>
<option value="CYAN" data-swatch="cyan">Cyan</option>
<option value="GRAY" data-swatch="grey">Grey</option>
</select>
With the slightly modified JavaScript, to use the HTMLElement.dataset
API to retrieve the value held in the custom data-swatch
attribute:
c.style.setProperty('--colour', selElmnt.options[j].dataset.swatch);
var x, i, j, selElmnt, a, b, c;
x = document.getElementsByClassName("custom-select");
for (i = 0; i < x.length; i++) {
selElmnt = x[i].getElementsByTagName("select")[0];
a = document.createElement("DIV");
a.setAttribute("class", "select-selected");
a.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
x[i].appendChild(a);
b = document.createElement("DIV");
b.setAttribute("class", "select-items select-hide");
for (j = 1; j < selElmnt.length; j++) {
c = document.createElement("DIV");
c.innerHTML = selElmnt.options[j].innerHTML;
c.style.setProperty('--colour', selElmnt.options[j].dataset.swatch);
c.addEventListener("click", function(e) {
var y, i, k, s, h;
s = this.parentNode.parentNode.getElementsByTagName("select")[0];
h = this.parentNode.previousSibling;
for (i = 0; i < s.length; i++) {
if (s.options[i].innerHTML == this.innerHTML) {
s.selectedIndex = i;
h.innerHTML = this.innerHTML;
y = this.parentNode.getElementsByClassName("same-as-selected");
for (k = 0; k < y.length; k++) {
y[k].removeAttribute("class");
}
this.setAttribute("class", "same-as-selected");
break;
}
}
h.click();
});
b.appendChild(c);
}
x[i].appendChild(b);
a.addEventListener("click", function(e) {
e.stopPropagation();
closeAllSelect(this);
this.nextSibling.classList.toggle("select-hide");
this.classList.toggle("select-arrow-active");
});
}
function closeAllSelect(elmnt) {
var x, y, i, arrNo = [];
x = document.getElementsByClassName("select-items");
y = document.getElementsByClassName("select-selected");
for (i = 0; i < y.length; i++) {
if (elmnt == y[i]) {
arrNo.push(i)
} else {
y[i].classList.remove("select-arrow-active");
}
}
for (i = 0; i < x.length; i++) {
if (arrNo.indexOf(i)) {
x[i].classList.add("select-hide");
}
}
}
document.addEventListener("click", closeAllSelect);
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none;
}
.select-selected {
background-color: #FFFFFF;
}
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #717171 transparent transparent transparent;
}
.select-selected.select-arrow-active:after {
border-color: transparent transparent #717171 transparent;
top: 7px;
}
.select-selected {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 6px 12px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
color: #494848;
font-size: 13px;
border-radius: 2px;
padding: 10px 16px;
line-height: 1.6;
border: 0.5px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
}
.select-items {
position: absolute;
background-color: White;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
.select-items>div {
display: grid;
grid-template-areas: "colour colourName";
grid-template-columns: 1em max-content;
grid-gap: 0.5em;
padding: 0.2em 0;
}
.select-items>div::before {
content: '';
background-color: var(--colour);
grid-area: colour;
}
.select-hide {
display: none;
}
.select-items div:hover,
.same-as-selected {
background-color: rgba(246, 245, 245, 0.9);
}
.myButton {
background-color: #286BEF;
border-radius: 6px;
border: 1px solid #ffffff;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: Arial;
font-weight: 550;
font-size: 13px;
padding: 12px 23px;
text-decoration: none;
position: absolute;
left: 280px;
}
.myButton:hover {
background-color: #0688fa;
}
.myButton:relative {
top: 10px;
}
* {
box-sizing: border-box;
}
.column {
float: left;
width: 40%;
padding: 10px;
}
.row:after {
content: "";
display: table;
clear: both;
}
p {
color: #494848;
font-family: Arial;
font-size: 13px;
}
<div class="row">
<div class="column">
<p>Notes</p>
</div>
<div class="column">
<div class="custom-select" style="width:200px;">
<select>
<option value="Please select a colour">Please select a colour</option>
<option value="RED" data-swatch="red">Red</option>
<option value="GREEN" data-swatch="green">Green</option>
<option value="BLUE" data-swatch="blue">Blue</option>
<option value="ORANGE" data-swatch="orange">Orange</option>
<option value="YELLOW" data-swatch="yellow">Yellow</option>
<option value="MAUVE" data-swatch="purple">Purple</option>
<option value="PALE_GREEN" data-swatch="palegreen">Pale green</option>
<option value="PALE_RED" data-swatch="lightcoral">Pale red</option>
<option value="PALE_BLUE" data-swatch="paleturquoise">Pale blue</option>
<option value="CYAN" data-swatch="cyan">Cyan</option>
<option value="GRAY" data-swatch="grey">Grey</option>
</select>
</div>
</div>
</div>
<br>
<a href="#" class="myButton">Submit</a>
References:
Bibliography: