One of the challenges of being a web developer is that sometimes you need to cram handfuls of content on a page like a manatee into a tube top without cluttering things up. Of course, Google is the king of simple and effective interfaces and they made a perfect way to show and hide long video descriptions under each YouTube video.
This is one of those things that is easy to overlook because it’s so easy to use that you don’t even think about it. Which is why it’s perfect to recreate for ourselves.
First lets set up the HTML
<div class="description"> <div class="description-text"> <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p> <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p> </div> <!-- description-text --> <div class="description-fadeout"></div> <button class="showhide" type="button" onClick="return false;" role="button"><span class="showhide-text">Show more</span></button> </div> <!-- description -->
The <div class="description">
encapsulates everything and the <div class="description-text">
is the actual content that we will be collapsing and expanding. The trigger will be controlled by <button class="showhide">
The CSS magic that shows and hides our content all boils down to the overflow property. When we want to hide our content we set a height for our div and set overflow: hidden
. This hides anything beyond the initial height set. When we want to show our content we will add the “expanded” class to our wrapper and set height: auto
to expand the div around all of our content.
.description { position: relative; /* To position the button */ } .description .description-text { height: 50px; /* Can be any value depending on how much you want to show */ overflow: hidden; } .description.expanded .description-text { height: auto; }
We also added position: relative
to the wrapper so that we can absolutely position our button to the bottom later.
The “Show more” button looks similar to a regular button but fades to white at the top, let’s add the gray to white gradient to our button’s class .description .showhide
. I created this gradient using the Ultimate CSS Gradient Generator
.description .showhide { background: rgb(255,255,255); /* Old browsers */ background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(239,239,239,1) 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(239,239,239,1))); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(239,239,239,1) 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(239,239,239,1) 100%); /* Opera11.10+ */ background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(239,239,239,1) 100%); /* IE10+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EFEFEF',GradientType=0 ); /* IE6-9 */ background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(239,239,239,1) 100%); /* W3C */ } }
Add the bottom-border
and border-radius
. Note that I’m declaring the other three borders to be 0 since browsers by default add a border to buttons
border: solid #ccc; border-radius: 0 0 5px 5px; border-width: 0 0 1px 0;
Make the cursor turn into a pointer when it hovers over the button, do a little more styling and position the button to be fixed at the bottom of the <div class="description">
wrapper.
cursor: pointer; /* If not in your css reset already */ font-size: 12px; height: 16px; padding: 0; position: absolute; bottom: 0; vertical-align: middle; width: 100%;
Some browsers maintain an outline around the button after you click it, lets turn that off
.description .showhide:hover, .description .showhide:focus { outline: 0; }
Add hover states to turn the gradient light blue
.description .showhide:hover { background: rgb(255,255,255); /* Old browsers */ background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(234,242,253,1) 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(234,242,253,1))); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(234,242,253,1) 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(234,242,253,1) 100%); /* Opera11.10+ */ background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(234,242,253,1) 100%); /* IE10+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EAF2FD',GradientType=0 ); /* IE6-9 */ background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(234,242,253,1) 100%); /* W3C */ }
Lastly let’s add the arrow next to the text, if you want to get fancy you can use sprites. However, I got lazy and just used single images
.description .showhide .showhide-text { background: url(img/down-arrow.gif) right no-repeat; padding-right: 12px; } .description .showhide:hover .showhide-text { background-image: url(img/down-arrow-hover.gif); } .description.expanded .showhide .showhide-text { background: url(img/up-arrow.gif) right no-repeat; } .description.expanded .showhide:hover .showhide-text { background-image: url(img/up-arrow-hover.gif); }
By now our button should be looking good, real good.
One last piece of CSS before we get to the jQuery. In order to get the user to click on the button you need to make it obvious that there is more content to be shown. So we’ll add a slight fade to cover up a portion of the text so it is REALLY obvious.
.description-fadeout { display: block; height: 8px; margin: 0; position: absolute; bottom: 16px; width: 100%; z-index: 999; background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0)), color-stop(100%,rgba(255,255,255,1))); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* Opera11.10+ */ background: -ms-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* IE10+ */ background: linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); /* W3C */ }
This empty div is positioned right above our button to create the fade effect. It takes advantage of RGBa alpha transparencies to make the fade visible when it is overlappint text or other content.
Let’s wrap this mother up. First load jQuery
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js" type="text/javascript"></script>
We’re going to code this so that we can use multiple of these show more buttons on each page. So lets wait for the DOM to get ready to manipulate and then create a function to interact with each button
<script type="text/javascript"> $(document).ready(function() { $('.description .showhide').each(function() {
Next define our variables in relation to each show more button, let’s define the button, the wrapper div and text inside the button so that we can change it’s text
var showHideButton = $(this), description = showHideButton.parent(), showHideText = showHideButton.children('span');
Finally when the user clicks the button, add the “expanded” class to the wrapper and change the text of the button. Then close everything up
showHideButton.click(function() { description.toggleClass('expanded'); showHideText.text(showHideText.text() == 'Show more' ? 'Show less' : 'Show more'); }); }); }); </script>
Put it all together
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { $('.description .showhide').each(function() { var showHideButton = $(this), description = showHideButton.parent(), showHideText = showHideButton.children('span'); showHideButton.click(function() { description.toggleClass('expanded'); showHideText.text(showHideText.text() == 'Show more' ? 'Show less' : 'Show more'); }); }); }); </script>