How to Create Accordion Menu in Pure CSS3


Topic: CSS3
Difficulty: Intermediate
Estimated Completion Time: 30 mins

In this tutorial we will learn how to create an accordion menu in pure CSS3. This menu was inspired in Futurico UI Pro. As we will create it with CSS this will only work on browsers and devices that support the :target pseudo-class selector.

Step 1 – HTML Markup

Create an unordered list with an anchor tag and a span tag. Add a different id for each list item and link to this id with the anchor tag. To be able to style and open the accordion when we click on it we need to use the :target selector. The target selector will only work if we will have a link that points to an id and when we click on that link the id becomes the target element. And with this way we are able to make the sub menu links visible.

<ul class="sub-menu">
	<li><a href="#one"><em>01</em>Dropbox<span>42</span></a></li>
	<li><a href="#one"><em>02</em>Skydrive<span>87</span></a></li>
<li><a href="#one"><em>03</em>FTP Server<span>366</span></a></li>

Step 2 – Menu Layout and Basic Styles

First of all we’ll add some reset styles to the menu to clear the margins, paddings, etc.

.accordion ul,
.accordion li,
.accordion a,
.accordion span {
	margin: 0;
	padding: 0;
	border: none;
	outline: none;

.accordion li {
	list-style: none;

Now let’s style the menu links. We will add a CSS3 gradient, some shadows and more basic styles for font, etc.

The menu will not have a fixed width. It will take the entire width of his parent, so if you want to give it a 300px width just create a div and give it the width that you want. In order to prevent layout issues we will give it a minimum width of 160px (110px width + 50px padding).

.accordion li &gt; a {
	display: block;
	position: relative;
	min-width: 110px;
	padding: 0 10px 0 40px;

	color: #fdfdfd;
	font: bold 12px/32px Arial, sans-serif;
	text-decoration: none;
	text-shadow: 0px 1px 0px rgba(0,0,0, .35);

	background: #6c6e74;
	background: -moz-linear-gradient(top,  #6c6e74 0%, #4b4d51 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6c6e74), color-stop(100%,#4b4d51));
	background: -webkit-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
	background: -o-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
	background: -ms-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
	background: linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);

	-webkit-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
	-moz-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
	box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);

To style the span that will contain some numbers we’ll give a gray background color, some shadows and rounded corners.

.accordion li &gt; a span {
	display: block;
	position: absolute;
	top: 7px;
	right: 0;
	padding: 0 10px;
	margin-right: 10px;

	font: normal bold 12px/18px Arial, sans-serif;
	background: #404247;

	-webkit-border-radius: 15px;
	-moz-border-radius: 15px;
	border-radius: 15px;

	-webkit-box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);
	-moz-box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);
	box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);

Step 3 – Icons

To insert the icons we will use the :before selector, this selector inserts content before the selected element. So this way we are able to insert the icons and position theme.

The icons images that we will use have 24px width and 24px height. So we’ll position them on top left and add some margins to center the icons properly.

.accordion &gt; li &gt; a:before {
	position: absolute;
	top: 0;
	left: 0;
	content: '';
	width: 24px;
	height: 24px;
	margin: 4px 8px;

	background-repeat: no-repeat;
	background-image: url(../img/icons.png);
	background-position: 0px 0px;

I’ve created a sprite image that contains all the icons (normal and hover state). The advantage of using sprites is that we are able to load all the icons at the same time (fewer requests) and as we only have one image that contain all icons the size will be inferior.

If you want to learn more about image sprites I recommend you to read this.

.accordion li.files &gt; a:before { background-position: 0px 0px; }
.accordion li.files:hover &gt; a:before,
.accordion li.files:target &gt; a:before { background-position: 0px -24px; }

.accordion li.mail &gt; a:before { background-position: -24px 0px; }
.accordion li.mail:hover &gt; a:before,
.accordion li.mail:target &gt; a:before { background-position: -24px -24px; }

.accordion &gt; a:before { background-position: -48px 0px; }
.accordion &gt; a:before,
.accordion &gt; a:before { background-position: -48px -24px; }

.accordion li.sign &gt; a:before { background-position: -72px 0px; }
.accordion li.sign:hover &gt; a:before,
.accordion li.sign:target &gt; a:before { background-position: -72px -24px; }

Step 4 – Sub Menu Links


To create the sub menus add another unordered list with the class of sub-menu inside of the list item that you want to have sub menus.

&lt;li id=&quot;one&quot; class=&quot;files&quot;&gt;&lt;a href=&quot;#one&quot;&gt;My Files&lt;span&gt;495&lt;/span&gt;&lt;/a&gt;

	&lt;ul class=&quot;sub-menu&quot;&gt;

		&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;em&gt;01&lt;/em&gt;Dropbox&lt;span&gt;42&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;

		&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;em&gt;02&lt;/em&gt;Skydrive&lt;span&gt;87&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;

		&lt;li&gt;&lt;a href=&quot;#&quot;&gt;&lt;em&gt;03&lt;/em&gt;FTP Server&lt;span&gt;366&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;



CSS Styles

The styles of the sub menu links are almost the same. We’ll only change the colors, shadows, etc. We also have added an “em” tag that will contain some enumeration.

.sub-menu li a {
	color: #797979;
	text-shadow: 1px 1px 0px rgba(255,255,255, .2);

	background: #e5e5e5;
	border-bottom: 1px solid #c9c9c9;

	-webkit-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
	-moz-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
	box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);

.sub-menu li:last-child a { border: none; }

.sub-menu li &gt; a span {
	color: #797979;
	text-shadow: 1px 1px 0px rgba(255,255,255, .2);
	background: transparent;
	border: 1px solid #c9c9c9;

	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	box-shadow: none;

.sub-menu em {
	position: absolute;
	top: 0;
	left: 0;
	margin-left: 14px;
	color: #a6a6a6;
	font: normal 10px/32px Arial, sans-serif;

Step 5 – Hover and Active states

For the hover and the current active link state we will change the gradient to a green one and also change the styles of the “span” to green. As in Futurico UI this accordion uses a pattern I have added it. You can choose if you want to use the pattern or the CSS3 green gradient. For the sub menu hover state only change the background color to a brighter one.

.accordion &gt; li:hover &gt; a,
.accordion &gt; li:target &gt; a {
	color: #3e5706;
	text-shadow: 1px 1px 1px rgba(255,255,255, .2);

	/*background: url(../img/active.png) repeat-x;*/
	background: #a5cd4e;
	background: -moz-linear-gradient(top,  #a5cd4e 0%, #6b8f1a 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a5cd4e), color-stop(100%,#6b8f1a));
	background: -webkit-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
	background: -o-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
	background: -ms-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
	background: linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);

.accordion &gt; li:hover &gt; a span,
.accordion &gt; li:target &gt; a span {
	color: #fdfdfd;
	text-shadow: 0px 1px 0px rgba(0,0,0, .35);
	background: #3e5706;

.sub-menu li:hover a { background: #efefef; }

Step 6 – Show and hide the sub menu

We’ll give 0px height to the sub menu to hide it and also add a transition slide effect. In order to make the slide transition work we need to give a fixed height to the sub menu. So if you want to add a different number of links to each sub menu you need to add a different height to each sub menu according to how many links you have. As I only have three links I use 98px height, if you want to make it automatic add a 100% height value but the slide effect will not work.

.accordion li &gt; .sub-menu {
	height: 0;
	overflow: hidden;

	-webkit-transition: all .2s ease-in-out;
	-moz-transition: all .2s ease-in-out;
	-o-transition: all .2s ease-in-out;
	-ms-transition: all .2s ease-in-out;
	transition: all .2s ease-in-out;

.accordion li:target &gt; .sub-menu {
	height: 98px;


We have finished this Pure CSS3 Accordion Menu. Hope you like it and don’t forget to live some feedback or any question you have in the comments.


Download Accordion Menu


  1. kseso Feb 29, 1:31 am

    Nice and good job.
    But there’s a little problem.
    The selected menu item jumps to the top of the window because you use the pseudo-element “:: target”.
    Do you know Chris Coyier´s tabs, whith “:checked”?

  2. kawa Feb 29, 11:05 am

    It’s a very good CSS tip, BUT
    but it’s using anchors and in a real page, not a preview, each time we click on an item, the page “move” to menu clicked and it’s very annoying. I personnaly prefer the accordion menu using checkboxes or radio rather than href.
    Whatever, thank you for this tutorial.

  3. Bogdan Silivestru Mar 2, 10:13 am

    You can actually move the transition from the UL.sub-menu to UL.sub-menu LI . This way, you can add any number of links without touching your styles.

  4. Heidi Mar 21, 3:14 pm

    Great tutorial.
    I have one little problem though; when I use the buttons the whole page jumps so the first li is in the top of the browser window.

    Any ideas how I can fix this?

  5. mboadi Mar 29, 11:32 am

    can anybody help me stop the sub menus from collapsing when its active. I tried commenting out the tranisition effects in the css but doesnot work submenus with links(only works submenus without links.). I need help ASAP. Please help me out.

  6. Adrian Apr 18, 8:19 am

    I’m trying to make each link in the sub-menu direct me to a different page, and therefore don’t want to use a href=”#one”, etc, rather each one will be unique (though I might have three or four items in each sub-menu)

    Am I correct in thinking that this menu concept isn’t going to work for me?

    Would be a shame, because it looks great, and this concept works well on phones

  7. #nycmixing Jun 1, 4:25 pm

    Question, how do you keep the window pane open when a link is selected, rather then having the selected area close as soon as the mouse stops hovering over the selected link?

  8. Shane-mng Jul 12, 11:05 pm

    This is a great way to make use of pseudo :target selector. At the same time, I notice users can not close the submenu by clicking on its parent LI element

  9. Lucas Sep 13, 9:22 pm

    Great – Which license ist that? Can i use the icons and the code on my page (not commercial)?

  10. Mirko Sep 16, 7:02 pm

    Thank’s for the great tip. I have tried to build my own accordion menu following your tutorial.
    The problem is that I am not able to style my submenu. It takes over the css of .accordion li > a and no matter what changes i make to .sub-menu li a, nothing happens…

    Any suggestions?

  11. Hugo Sep 29, 11:55 am

    Hi. This tutorial is great. I have adapted the design to my needs and it works perfectly. Thank you!!
    I just have one question left: is there a way to add a sub-menu to the sub-menu? I added one more unordered list and styled it. But the animation doesn’t work like i would like to. Ideally the second sub-menu list should expand only when i hover it’s parent in the first sub-menu… Any idea how to achieve that?

  12. googs Oct 23, 6:35 pm

    I am facing a problem, if we have not a sub menu a want to give a hyper link on the main menu then how do it. please help me.

  13. WheelieSimple Jan 5, 1:24 am

    I am trying to have variable height submenus. Help! I have tried max and min height and neiher works.

  14. Ronald Jan 8, 3:37 am

    why is it that my sub menu is not hiding?

  15. Marcy Jan 27, 9:58 pm

    Help! I cannot get the sub menus to hide. They just stay open all the time. How is this accomplished?
    Everything else works & looks great though. Thanks for this tutorial!

    • M Dec 24, 6:33 pm

      I am having the same problem with the submenus constantly open. I thank you in advance for any advise.

  16. Ryan Johnston Mar 13, 7:19 pm

    Awesome example, thanks for sharing!

    Is there a way to extend this example to allow for 3 levels?

    I’d very much like to use this menu example, but I can’t figure out how to add a third menu. Any help would be greatly appreciated!

  17. Kevin Morrissey Mar 28, 1:04 am

    Excellent CSS menu, thanks for sharing.

    Just a little upgrade to consider. If you have more than 3 menus the height of 98px needs to be changed but if you are generating the ul and li tags from a database with json like I am the height needs to be dynamic. so…

    .accordion li:target > .sub-menu {
    height: auto;

    changing the height to auto allows unlimited submenus.

    • Heejin Jo May 16, 7:48 pm

      I’ve tried what you suggested, but

      .accordion li:target > .sub-menu {
      height: 100%;

      would be better than ‘auto’:)

  18. E.W. Apr 23, 4:16 pm

    Very good! Big thanks!

    How about “sub-sub-menu” and “sub-sub-sub-menu” and so on?
    And my body’s height is over 4000px, is that possible to stop scrolling to #three?

  19. auditya Jul 6, 1:29 pm

    when i download
    there’s a cssrefresh.js on

    but i can’t find it anywhere

  20. Murat Jul 10, 9:27 am

    .accordion li:target > .sub-menu {
    height: 98px;

    What should I do when there’s more than 3 sub-menu elements in the menu? It’s ok to use 98px for any 3 itemed menu but if the menu has more than 3 items, 4th and other items doesn’t show. Is there a way to expand the menu according to the sub-menu items inside it?

  21. Andre Aug 1, 10:56 pm

    Very nice menu.
    One more question: How can i add a third level?
    MyFiles >> Dropbox >> Private

  22. Dims Aug 17, 5:50 pm


    Thanks for this menu but one question for me, is it full compatible with IE ?

    If not, what are we need to modify for it ?

  23. Mark Aug 31, 9:53 pm


    This is a really great tutorial, i have been looking for a slick accordion style solution i can use in my project, and this looks impressive.

    Is it possible to make the menu items open and close on Mouse Hover ?

    Currently, you have to click on the menu item for it to open, can this be done using Mouse Hover ??

    Thank you, and thank you for a great solution, i have also seen alot more of your other items and products, really stunning work. I look forward to using you again in the near future.


  24. Joseph Oct 2, 10:17 pm

    Good and simple design. It helped me lot.
    Thanks alot.

  25. andrea Nov 11, 9:20 pm

    Very very good one. Just one thing. How can I make this responsive so that he can adapt to any device if I shrink the window?

  26. Robbie Apr 12, 6:27 pm

    Thanks for the tutorial. It obviously works well, and it’s exactly what I’m looking for, but I’m a coding beginner (ish) and I’m not able to get it to work. I’m unclear where to paste all of this code. I’ve read about externally linking the html code to the css code which I think I’ve got figured out, but when I publish- I’m not seeing any of the css properties for the menu. Any help on where to go to search for it?

    Thank you in advance

  27. Caleb Jun 13, 7:42 pm

    Hi, thanks for the tutorial, my only question is what I can do if I want to have a different number of items under each sub menu. In one I have 3 items but in another I have 7, is there any way to make this work without making several different classes of sub-menus? Thanks!

  28. Lem Nov 25, 10:42 am

    Ive created a few accordion menus with :target
    Two things I still haven’t been able to implement:

    1. Click to Close the accordion.
    2. Multiple independent “Groups” of accordions where there is no interaction between groups of different name.

    id love to have some advice on how it can be done without JS if possible.
    Cheers, Lem

  29. adil Dec 24, 1:42 pm

    hi. i tried but the sub menu doesn’t hide at all….how to fix this? i am using chrome btw.

Leave a Reply

* Minimum length: 20 characters