Quantcast
Channel: demo – PEPSized
Viewing all articles
Browse latest Browse all 10

Css-only Alternative to the Select Element

$
0
0

In this tutorial, I will present you my alternative solution to the select form tag. It’s css-only and it looks simple but really nice. We will use a list of radio elements, styled as a drop-down list, that will look and behave similarly to the select element.
Of course you have to provide some fallback for mobile devices (and IE8 if you wish). I discuss that briefly in the final part of this tutorial.
Check the demo and choose your favorite beer.

Step 1 – HTML

Here is the html we use within a form

<fieldset class="radio-container">
	<div class="radio-options">
		<div class="toggle">Choose your beer</div>
		<ul>
			<li>
				<input type="radio" name="my-beer" id="choice1" value="choice1">
				<label for="choice1">Cul Dorcha</label>
			</li>
			<li>
				<input type="radio" name="my-beer" id="choice2" value="choice2">
				<label for="choice2">Rowers Red Ale</label>
			</li>
			<li>
				<input type="radio" name="my-beer" id="choice3" value="choice3">
				<label for="choice3">Belfast Ale</label>
			</li>
			<li>
				<input type="radio" name="my-beer" id="choice4" value="choice4">
				<label for="choice4">O'Hara Irish Stout</label>
			</li>
		</ul>   
	</div>
</fieldset>

Step 2 – The idea

To make things simple I tried to “sketch” my idea. I hope it is clear enough.
Css-only select drop-down list

Step 3 – CSS

Let’s add some css that reflect the idea presented in the scheme above. For the brevity of this tutorial I omit some parts of the css (e.g. triangle arrows) that only add some visual flavor – you’ll find the complete version in the attached files.
Note that the vendor prefixes are omitted for the same reason.
For the outer containter (“.radio-container”) we’ll have

radio-container {
  position: relative;
  height: 4em; /* 3em (being the max-height of the inner container) + 1em ("margin") */
 }
.radio-container:hover {
    z-index: 9999; }

And for the inner one

.radio-options {
  position: absolute;
  max-height: 3em;
  width: 100%;
  overflow: hidden;
  transition: 0.7s;
}
.radio-options:hover {
  max-height: 100em; 
}

Next

.radio-options .toggle {
    position: relative;
    cursor: pointer;
    padding: 0.75em;
    background: darkgreen;
    border-radius: 10px;
    z-index: 1; }
/* li are stacked at the same position as .toggle, only .toggle is visible */
  .radio-options li {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%; 
  }
  .radio-options label {
    display: block;
    opacity: 0;
    transition: 0s; }

We hide the inputs, we could just use display : none, but that would not work in browsers (some mobile ones) where clicking the label does not focus the associated input.

.radio-options input {
  position: absolute;
  top: 0;
  left: 0;
  width: 300px;
  height: 3em;
  opacity: 0;
  z-index:1;
  cursor: pointer; 
}

Step 4 – What happens on hover – CSS continued

Now let’s look closer at what happens on hover, already : .radio-container gets a high z-index and .radio-options increases its max-height, we’ll add

/* li elements have a normal flow within the .radio-options container */
.radio-options:hover li {
    position: relative; }
.radio-options:hover label {
    opacity: 1;
    transition: 0.5s; }

Step 5 – input:checked

To style the checked option we will use the general sibling selector. It uses a tilde character combinator (E ~ F) and matches elements that are siblings of a given element. The first element (E) has to occur before the second (F) one and they have to share the same parent (li items in our case).
If one of the radio is checked, we’ll see its label instead of the toggle :

.radio-options input:checked ~ label {
   position: absolute;
   top: 0;
   left: 0;
   right: 0;
   opacity: 1;
/* is above the .toggle so is visible */
   z-index: 2;
/* has tha same styles as .toggle */
   padding: 0.75em;
   background: darkgreen;
   border-radius: 10px; }

On hover it returns to the normal flow

.radio-options:hover input:checked ~ label {
  position: static;
  border-radius: 0; }

Step 6 – What about mobile devices

Since our element is activated on hover you’ll have to provide some fallback for touch devices. One solution is to leave the radio labels visible all the time not only on hover.
Here is my solution to keep the drop-down list, I detect the touch devices with a custom modernizr build and add the following script

$(document).ready(function(){
	if (Modernizr.touch) {
			$(".radio-options").bind("click", function(event) {
				if (!($(this).parent('.radio-container').hasClass("active")))	{
				$(this).parent('.radio-container').addClass("active"); 
				event.stopPropagation();
				}
			});	
	$(".toggle").bind("click", function(){ 
		$(this).parents('.radio-container').removeClass("active"); 
		return false;
		 });  
	}
});

In my css I modify every :hover definition like that

.no-touch .radio-container:hover, .active.radio-container  {
    z-index: 9999; }
.no-touch .radio-options:hover, .active .radio-options {
  max-height: 100em; 
}
.no-touch .radio-options:hover li,  .active .radio-options li {
    position: relative; }
.no-touch .radio-options:hover label, .active .radio-options label {
    opacity: 1;
    transition: 0.5s; }
....

Step 7 – What about IE8

Again, it’s up to you, the fallback solutions are not the main part of this tutorial. Here is my approach:

<!-- [if (IE 8)]>
<script>
        $(document).ready(function(){
                $(".radio-options li").bind("click", function() {
                        $(this).siblings(".checked").removeClass("checked");
                        $(this).addClass("checked");
                });
        });
</script>
<![endif]-->

I have to add to my css the .checked class declarations, e.g. (see the attached files for the complete version):

.radio-options .checked label {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 0.75em;
  background: #1b9e4d;
  visibility: visible;
  z-index: 2; }
....

That’s all. I hope you’ll find this technique useful, let me know what you think. Thanks.

Terms of use :

You may use the effects demonstrated in tutorials in your own work, both commercial or non-commercial without any attribution. You may not reproduce entire nor large parts of our tutorials. The outcome of our tutorials may not be re-saled nor redistributed.


Viewing all articles
Browse latest Browse all 10

Trending Articles