Four-region selection box

Is there a way to create a quad state checkbox without using a set of images for various icons? I know how to have a tri-state checkbox with indeterminate, but I need to rotate through 4 states. Are there any more elegant solutions available?

Answer №1

By using radio buttons and some CSS (CSS3), you can create a similar effect of cycling through states without the need for JavaScript:

.cyclestate {
 display: inline-grid;
}
.cyclestate label {
 grid-area: 1 / 1;
 background-color: white; 
 color: black;
 z-index: 0;
 opacity: 0;
}
.cyclestate input {
 position: absolute;
 z-index: -1;
}
.cyclestate input:checked + label {
 opacity: 1;
}
.cyclestate input:first-of-type + label {
 z-index: 2;
}
.cyclestate input:checked + label + input + label {
 opacity: 0;
 z-index: 2;
}
/* -- Unrelated and accessibility -- */
.cyclestate { border: none; padding: 0; }
.cyclestate legend { position: absolute; }
.cyclestate label { padding: 1em; text-align: center; display: inline-block; cursor: pointer; user-select: none;
}
.cyclestate label::before { content: '← '; }
.cyclestate label::after { content: ' →'; }
.cyclestate label::before, label::after { color: transparent; }
.cyclestate input:focus-visible + label { outline: solid; }
.cyclestate input:focus-visible + label::before,
.cyclestate input:focus-visible + label::after { color: currentcolor; }
:root { background: dimgray; color: snow; }
:link { color: aqua; } :visited { color: lime; }
<fieldset class="cyclestate">
  <legend>Pick a number</legend>
  <input id="one" type="radio" name="r" checked>
  <label for="one">One</label>
  <input id="two" type="radio" name="r">
  <label for="two">Two</label>
  <input id="three" type="radio" name="r">
  <label for="three">Two Plus One</label>
  <input id="four" type="radio" name="r">
  <label for="four">Four</label>
</fieldset>

<p><button onclick="x.classList.toggle('cyclestate')">Toggle condenseness ↑</button>

This method involves layering labels on top of each other using modern CSS techniques like grid, ensuring that only the checked input's label is visible while maintaining accessibility.

(Note: Testing with screen readers and older browsers is recommended.)


The original 2015 snippet provided has questionable accessibility practice, it is advised to avoid using it altogether:

.cyclestate input:not(b),
.cyclestate input:not(b) + label {
  display: none;
}
.cyclestate input:checked + label {
  display: inline-block;
  width: 4em;
  text-align: center;
  -webkit-user-select: none;
  -moz-user-select: none;
  -webkit-appearance: button;
  -moz-appearance: button;
}
<span class="cyclestate">
  <input type="radio" name="foo" value="one" id="one" checked>
  <label for="two">one</label>
  <input type="radio" name="foo" value="two" id="two">
  <label for="three">two</label>
  <input type="radio" name="foo" value="three" id="three">
  <label for="four">three</label>
  <input type="radio" name="foo" value="four" id="four">
  <label for="one">four</label>
</span>

Using this method allows for a compact visual representation of multiple states in one place, with clear values on the server side.

However, it should be noted that this usage of labels may exploit the feature of label targeting different input than described.

Answer №2

It is possible to give the appearance that a checkbox has three states, but in reality, it will always have only two options available.
Furthermore, achieving the "indeterminate" visual state is not inherent to the default user interface and requires programmatic activation:

var box = document.getElementById('box'),
    checked = document.getElementById('checked'),
    indet = document.getElementById('indet');
var update = function()
{
    checked.textContent = box.checked;
    indet.textContent = box.indeterminate;
};
box.addEventListener('click', update);
document.getElementById('a').addEventListener('click', function()
{
    box.checked = true;
    update();
});
document.getElementById('b').addEventListener('click', function()
{
    box.checked = false;
    update();
});
document.getElementById('c').addEventListener('click', function()
{
    box.indeterminate = true;
    update();
});
document.getElementById('d').addEventListener('click', function()
{
    box.indeterminate = false;
    update();
});
<input type="checkbox" id="box"><br>
<button id="a">On</button> <button id="b">Off</button><br>
<button id="c">Indeterminate</button> <button id="d">Clear indeterminate</button>
<div>box.checked: <span id="checked"></span></div>
<div>box.indeterminate: <span id="indet"></span></div>

In response to your inquiry:

There currently isn't a built-in method to introduce a fourth visual (or actual) state to a checkbox, although this doesn't mean resorting to using images is necessary.
It's feasible to style an element resembling a checkbox and utilize JavaScript to simulate a rotation of states:

var state = 0;
var toggle = document.getElementById('toggle');
toggle.addEventListener('click', function()
{
    state = (state + 1) % 4;
    toggle.className = 'state' + state;
});
#toggle
{
    border: solid 1px #666;
    border-radius: 3px;
    width: 14px;
    height: 14px;
}
.state0
{
    background: linear-gradient(#DDD, #FFF);
}
.state1
{
    background: linear-gradient(#F00, #C00);
}
.state2
{
    background: linear-gradient(#FF0, #CC0);
}
.state3
{
    background: linear-gradient(#0F0, #0A0);
}
<div id="toggle" class="state0"></div>

Ultimately, alternatives beyond traditional checkboxes will be required.

Moreover, implementing a checkbox-like entity with more than two states can be confusing, so I encourage exploring options designed for multiple selections like radio buttons or dropdown lists.

Answer №3

Unfortunately, it is not currently feasible. However, for those interested, there is a helpful resource that explains how to utilize three states, including the indeterminate state: https://css-tricks.com/indeterminate-checkboxes/

You will need to devise an alternative solution by incorporating your own icons and essentially creating a customized form control. One potential design approach that addresses the requirement for multiple states involves:

Utilizing a series of icons, reminiscent of Gmail's star system. In Gmail, clicking on the star changes its color, and after a certain number of clicks (around 10), other icons like exclamation points and checkmarks appear.

Link your various state specifications with the icon currently in use (or the position within the icon list).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

PHP dropdown menu is a dynamic feature that provides users

Can anyone help me identify the issue with this code? I am struggling to display the sub menu... I suspect the problem lies in the section where I retrieve the sub menu from the database. However, upon inspection, everything seems correct... It's po ...

Generate visual representations of data sorted by category using AngularJS components

I am facing an unusual issue with Highcharts and Angularjs 1.6 integration. I have implemented components to display graphs based on the chart type. Below is an example of the JSON data structure: "Widgets":[ { "Id":1, "description":"Tes ...

Remove all HTML tags except for those containing a specific class

Looking for a regex that removes all HTML tags except the "a" tags with the "classmark" class For example, given this HTML string: <b>this</b> <a href="#">not match</a> <a href="#" target="_blank" ...

Centralizing images in a Facebook gallery/lightbox during the loading process

Is the image width and height stored in Facebook's gallery database? In typical JavaScript usage, the image width and height cannot be determined until the image is fully loaded. However, on Facebook, images are pre-loaded before being displayed, ens ...

Adjusting the text of a button when hovering over it will also trigger a resizing of the

Currently, I am facing an issue where the bootstrap button's size changes when hovered over. My intention is to have the bootstrap button remain a fixed size while only the text inside it changes using javascript for mouseover and mouseout events. How ...

Background and checked styles for radio buttons

Thank you in advance for any assistance you can provide. I am looking to create a unique radio button design. When the radio button is not checked, I want it to display as a simple white circle. However, once it is checked, I would like it to appear eithe ...

Exploring Objects within an array using Angular loops

Hey there, I'm currently working on an Angular project and I need to retrieve the userName of the user for each comment that is posted. These entities are coming from my Spring Boot project. Is there a way to access the username for every comment? He ...

Assistance with Php: Need help with remote addresses (I'm a complete beginner in php, apologies)

Hello, I have encountered an issue with some PHP code from OpenCart that is automatically inserting <br /> and commas "," into the addresses of all my customers in the order notification emails. This unintended addition is creating problems with the ...

Conceal the PayPal Button

Currently, I'm facing a challenge where I need to dynamically show or hide a PayPal button based on the status of my switch. The issue is that once the PayPal button is displayed, it remains visible even if the switch is toggled back to credit card pa ...

What is the method for assigning a class name to a child element within a parent element?

<custom-img class="decrease-item" img-src="images/minus-green.svg" @click="event => callDecreaseItem(event, itemId)" /> Here we have the code snippet where an image component is being referenced. <template&g ...

Distributing elements evenly across the parent width using Angular FlexLayout for a responsive design

I need to create 3 div squares: div-left, div-middle, and div-right, each with a width of 300px. These squares should be arranged horizontally within the parent div main-section, which will adjust its size based on the screen width, being 1300px if the scr ...

I am looking for a way to add some color to the text within a div on my HTML page. Can you help me

Is there a way to apply background color only to the text content within this div, without styling the entire element? ...

Ensure that the <TabPanel> content occupies the entire width and height of its parent container

Currently, I am working with React and material-ui. Specifically, I am utilizing an appbar with tabs and my goal is to have the content of each tab expand to full width and height when selected. If you'd like to see an example, check out this sandbox ...

Immediate display of collapsed/toggle menu in a Bootstrap navbar

I have created a bootstrap responsive navigation menu that collapses into a box when the page is resized. It's a standard menu with bootstrap, but I'm facing an issue where the menu automatically appears when the page gets small instead of needin ...

Identify a specific HTML template using jQuery

I am currently working on implementing datepickers in various HTML templates. The issue I am facing is that the functionality only seems to work in my index.html file. When I try to replicate the same setup in another template, it does not function proper ...

What is the answer to this issue where the entity name is required to directly come after the "&" in the entity reference?

Whenever I insert the code into my Blogger platform, an error pops up stating: The entity name must directly follow the '&' in the entity reference Here is the code: <script> if (typeof bc_blocks == "undefined" && wind ...

Populate JQuery fields dynamically based on changing name elements

I am working on a section that displays products dynamically fetched from a database using an ajax call. The results vary, some are single-row while others have multiple rows. Initially, I have a placeholder row of HTML on the main page for data entry whic ...

What is preventing me from updating one dropdown list based on the selection made in another dropdown list?

I have a situation on a classic asp page where there are two dropdown lists: <select id="ddlState" name="ddlState" runat="server"> <option value="KY">Kentucky</option> <option value="IN" ...

An HTML document may display a segment of a URL

Is there a way to display part of a URL in an HTML document, so that if the URL changes, the corresponding content in the body also updates? For instance, www.example.com/?key=i - Is it possible for this link to be dynamically displayed within the body o ...

The v-select menu in Vuetify conceals the text-field input

How can I prevent the menu from covering the input box in Vuetify version 2.3.18? I came across a potential solution here, but it didn't work for me: https://codepen.io/jrast/pen/NwMaZE?editors=1010 I also found an issue on the Vuetify github page t ...