Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to toggle two CSS `:checked` pseudo-classes with one click?

Tags:

css

Please note that I am aware of this question but I am looking for specifically a technical answer.

As a CSS challenge to myself I'm trying to create a fancy select box using only CSS. Using a variety of fancy techniques that I've learned recently, I've gotten pretty far.

Codepen Here

  • It looks good
  • Is fully style-able,
  • It opens up in a list on click (using a hidden checkbox and a :checked+label selector)
  • Allows placeholder text (using :checked and a negative margin-top)
  • Allows selection (using a nested radio button list)
  • And displays value properly when selected and collapsed (using :checked and position: absolute)
  • It will even bind javascript correctly

This is using a structure similar to

input[type=checkbox]#selector
label[for=selector]
    ul
        li.item1
            input[type=radio]#item1
            label[for=item1] The First Item 

I have just one problem left, once expanded, closing the menu on click doesn't work properly. A normal selectbox will close when clicking on an item. Mine won't until you click near the border of the selectbox.

Closed CSSelectbox

Open CSSelectoox

That is because the user is clicking on the inner input which won't toggle the :checked state of the parent label, they need to click around the input to close the selectbox.

Is there any way to make both the radio button state and the parent state toggle at the same time?

like image 793
George Mauer Avatar asked Aug 09 '14 04:08

George Mauer


People also ask

How do I use two pseudo-classes in CSS?

:last-child is a pseudo-class, whereas :after (or ::after in CSS3) is a pseudo-element. To quote the standard: Pseudo-classes are allowed anywhere in selectors while pseudo-elements may only be appended after the last simple selector of the selector. This means your syntax is correct according to CSS2.

Can you use multiple pseudo-class selectors with an element?

You can combine several CSS pseudo-elements for one element. However, you cannot use CSS ::after two times or ::before two times.

Can you combine pseudo selectors?

If you're talking about pseudo-classes, then yes, you can combine them in any order.

Which of the following statements are correct about the CSS pseudo-classes?

They can be used for styling visited and unvisited links differently. They can be used for styling an element when it gets focus. Answer: They can be used for styling an element when you hover mouse on it.


4 Answers

Possible you might be overcomplicating this a bit.

Why not just change your .country-selector checkbox into a radio button in the same group? Then it has exactly the behavior you're looking for without making it a situation that requires lots of workaround. The only concern would be providing an empty value for if the user were to submit while the box is still open, but that's a concern with your existing implementation anyhow.

Codepen Example

Jade

input#country-selector(type='radio', name="country")

SCSS

&>[type=checkbox]

becomes

&>[type=radio]

I made a few styling changes to the pen as well to bring it inline with more traditional select dropdowns.

Very interesting idea. Kudos on that.

like image 75
Josh Burgess Avatar answered Oct 09 '22 23:10

Josh Burgess


edit

internet explorer will treat a transparent element like event-pointer:none; there for one has to add a background-color + opacity:0. At least one can open it in internet explorer now: http://codepen.io/anon/pen/EargxL

edit 2

i finally found a way to support internet explorer, it looks a bit crappy atm, i will refactor it another day :p http://codepen.io/anon/pen/ogmqpq

please note it will not work on most mobile devices as the dont implement :active pseudo-selector: http://www.quirksmode.org/css/selectors/mobile.html#link5

original

In short, it is almost impossible to trigger two toggles by checked selector on different inputs with only one click.

How ever one could use the :focus pseudo-selector in combination with :active.

<div class="dropDown">
    <div class="toggle" tabindex="0"></div>
    <ul class="list" tabindex="0">
        <li>
            <label>
                <input type="radio" name="myDropDown" value="someValue" checked="checked"/>
                <span>Item 1</span>
            </label>
        </li>
        <li>
            <label>
                <input type="radio" name="myDropDown" value="someValue"/>
                <span>Item 2</span>
            </label>
        </li>
        <li>
            <label>
                <input type="radio" name="myDropDown" value="someValue"/>
                <span>Item 3</span>
            </label>
        </li>
    </ul>
</div>

CSS:

ul {
    list-style:none;
}
input {
    display:none;
}
.dropDown {
    position:relative;
}
.dropDown .toggle {
    position:absolute;
    width:100%;
    height:100%;
    z-index:1;
    outline:none;
}
.dropDown > .toggle:focus {
    z-index:0;
}
.dropDown > .list {
    position:relative;
    outline:none;
}
.dropDown > .list:active {
    z-index:1;
}
.dropDown > .toggle:not(:focus) + .list:not(:active) input:not(:checked) + span {
    display:none;
}

live example http://codepen.io/anon/pen/emxJWr

note: this will not work in internet explorer because :active is not bubbling up, im open for any suggestions!

like image 39
ChaosClown Avatar answered Oct 09 '22 22:10

ChaosClown


just for the curiosity of pointer-events: a doubleclick on a input:checked + label will allow you here to close your fancy selector : http://codepen.io/gc-nomade/pen/NPJaNa

.options {
      &>li{
        &:hover {
          background-color: blue;
        }
        input[name=country]:checked+label {
          position: static;
          pointer-events:none;}
      }
    }
like image 3
G-Cyrillus Avatar answered Oct 09 '22 21:10

G-Cyrillus


Changing the z-index will allow the user to click on the label area which toggles your drop down.

See my updated codepen: codepen ex

  .country-selector {
  display: inline-block;
  border: 1px solid black;
  position: relative;
  overflow: hidden;

  &:before {
    content: "▾";
    position: absolute;
    right: 5px;
    top: 5px;
    z-index:-1;
  }

Changed the .country-selector .options margin and took off the .country-selector padding-right.

Then changed the .country-selector:before to z-index of -1.

Not sure if this will work across all browsers/devices but does seem to work on FF and chrome (OS x).

Hope this helps:)

like image 2
yo-yo Avatar answered Oct 09 '22 23:10

yo-yo