37

I have a menu in a tag called sf-menu.

I need the visibility to change to none when the link is clicked and toggled back when clicked again.

Can I achieve this with CSS only or do I need JavaScript?

Hoping someone can help me with an example.

.sf-menu {visibility: visible}
<a class="closed" href="#sidewidgetarea"> Switch</a>
altocumulus
  • 21,179
  • 13
  • 61
  • 84
Erik
  • 5,701
  • 27
  • 70
  • 119
  • 1
    You can do it with css. :target psuedo selector is the only way to do it with only css. You can see the detailed info from here. https://css-tricks.com/on-target/ – ebilgin Oct 02 '15 at 13:24

12 Answers12

37
  1. You can use input type='checkbox' for it :

http://jsfiddle.net/gSPqX/1/

<input type="checkbox" style="display: none" id="cb">
<label for="cb">Click Here</label>
<div>
    Hello. This is some stuff.
</div>
  1. One more better solution using :target

#menu .menu{
   display:none; 
}
#menu:target  .menu{
    display: block;
}

#menu:target .menu__open{
    display: none;
}
#menu .menu__close{
    display: none;
}
#menu:target .menu__close{
    display: block;
}
<div id="menu">
    <a href="#menu" class="menu__open">Open menu</a>
    <a href="#" class="menu__close">Close menu</a>
    <div class="menu">
        Hello. This is some stuff.
    </div>
</div>
Raphaël Vigée
  • 2,048
  • 14
  • 27
sglazkov
  • 1,046
  • 1
  • 10
  • 38
  • I'm not using checkboxes. – Erik Sep 21 '15 at 00:46
  • use second solution with :target – sglazkov Sep 21 '15 at 00:49
  • 4
    First solution isn't answer for this question, but second one is. This answer should be accepted one. – ebilgin Oct 02 '15 at 13:23
  • 2
    @Eirk I agree this is the only pure css way i can think of achieving this. There are something's to keep in mind when using :target though. I'd use these rules-of-thumb for when :target is a good choice: When a "state" is needed. When the jump-down behavior is acceptable. When it's acceptable to affect the browser history. Taken from https://css-tricks.com/on-target/ – partypete25 Oct 08 '15 at 00:15
  • I guess in case of single page apps (where hashbang URLs are used) this approach will have issues. Instead JS / JQuery or even the checkbox based approach is much better. – Vivek Athalye Nov 01 '15 at 11:10
8

If you are using jquery, you can use jquery.toggle()

Example:

$(".closed").click(function(event) {
    event.stopPropagation()
    $(".sf-menu").toggle();
});

Source: https://api.jquery.com/toggle/

Hieu Le
  • 738
  • 4
  • 8
5

You can do it using only CSS. The trick is to leave a trail that could be clicked and work as a switch/button for turning display on or off. You can accomplish that by wrapping your content needed to be toggled into some div or any other element suitable to you.

Here is a little example for that.

label {
  cursor: pointer;
}
#menu-toggle {
  display: none; /* hide the checkbox */
}
#menu {
  display: none;
}
#menu-toggle:checked + #menu {
  display: block;
}
<label for="menu-toggle">Click me to toggle menu</label>
<input type="checkbox" id="menu-toggle"/>
<ul id="menu">
  <li><a href="#">First link</a></li>
  <li><a href="#">Second link</a></li>
  <li><a href="#">Third link</a></li>
</ul>
Haseeb Zulfiqar
  • 316
  • 3
  • 11
1

Here is a super simple solution in jQuery, using the tags you have mentioned. But first remove your CSS-row!

Please not that this example doesnät seem to execute on stackoverflow.com but works fine on jsfiddle.net.

$('.closed').click(function(){
    $('.sf-menu').toggle();
});
<a class="closed" href="#sidewidgetarea">Switch</a>
<div class="sf-menu">The menu</div>
Fabian Mossberg
  • 238
  • 4
  • 11
1

In HTML :

<h1 class="sf-menu"> TestText </h1>

JavaScript :

 var sfmenu = document.getElementsByClassName("sf-menu");
sfmenu[0].onclick = function () {
    if (this.style.display == 'none' ) {
        this.style.display = '';
    } else {
        this.style.display = 'none';
    }
};
Osama AbuSitta
  • 3,918
  • 4
  • 35
  • 51
1

If you're able to edit the DOM, there is a PureCSS solution (see below), but I think that the best solution is using Javascript, jQuery offers you a crossbrowser solution!

Hope Helps!!

var HIDDEN_CLASS = 'sf-menu-hidden';


/** jQuery **/
jQuery(document).ready(function($) {
  $('#jQueryTest .closed').click(function closeWithJQuery(event) {
    event.preventDefault();
    $('#jQueryTest .sf-menu').toggleClass(HIDDEN_CLASS);
  });
});


/** VanillaJS **/
document.addEventListener("DOMContentLoaded", function(event) {
  document
  .querySelector('#VanillaJSTest .closed')
  .addEventListener('click', function() {
    var el = document.querySelector('#VanillaJSTest .sf-menu');
    var task = el.classList.contains(HIDDEN_CLASS) ? 'remove' : 'add';
    
    el.classList[task](HIDDEN_CLASS);
  });
});
* {
  -webkit-user-select: none;
  user-select: none;
}

.sf-menu-hidden {
  visibility: hidden;
}

a, label {
  cursor: pointer;
}

article + article {
  margin-top: 10px;
  border-top: 1px solid green;
}

#PureCSSTest [type="checkbox"] {
  display: none;
}

#PureCSSTest [type="checkbox"]:checked + .sf-menu {
  visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<article id="jQueryTest">
  <h1>Test jQuery</h1>
  <a class="closed">TOGGLE MENù</a>
  <div class="sf-menu">
    <ul>
      <li> Hey I Am On THE SCREEN</li>
    </ul>
  </div>
</article>


<article id="VanillaJSTest">
  <h1>VanillaJS</h1>
  <a class="closed">TOGGLE MENù</a>
  <div class="sf-menu">
    <ul>
      <li> Hey I Am On THE SCREEN</li>
    </ul>
  </div>
</article>


<article id="PureCSSTest">
  <h1>PURE CSS</h1>
  <a class="closed"><label for="toggleClosed">TOGGLE MENù</label></a>
  <input type="checkbox" id="toggleClosed">
  <div class="sf-menu">
    <ul>
      <li> Hey I Am On THE SCREEN</li>
    </ul>
  </div>
</article>
Hitmands
  • 13,491
  • 4
  • 34
  • 69
0

CSS:

.myVisibleLink{
     display:block;
}
.myHiddenLink{
     display:none;
}

Jquery:

var myFlag = false;
$(function() {                       //run when the DOM is ready
  $("#IDOfLink").click(function() {  //use a class, since your ID gets mangled
      if(myFlag == false){    
           myFlag = true;
           $(this).addClass("myHiddenLink");      //add the class to the clicked element
      }else{
           myFlag = false;
           $(this).addClass("myVisibleLink");      //add the class to the clicked element
     }
  });
});
0

You can achieve this with pure Javascript.

Use the onclick event for the anchor tag.

function OnsidewidgetareaClick()
{
 var elementObj = document.getElementsByClassName("sf-menu")[0];
  
  if (elementObj.style.display == 'block' ||elementObj.style.display=='')
    {
        elementObj.style.display = 'none';
    }
    else 
    {
        elementObj.style.display = 'block';
    }
 
}
.sf-menu {visibility: visible}
<a class="closed" href="#sidewidgetarea" onclick="OnsidewidgetareaClick();"> Switch</a>

<div class="sf-menu">
  This is the .sf-menu element.
</div>
Kishore Sahasranaman
  • 4,013
  • 3
  • 24
  • 50
0

Maybe this can help.Using this will hide your menu on click and then as per your requirement remove or add class afterwards.

#sf-menu:active{
    display:none;
}
Cheezy Code
  • 1,685
  • 1
  • 14
  • 18
0

I like the handy "checkbox" solution in responses, pure CSS. However if you need the link to be involved, you may try to utilize the onclick attribute in the link HTML code.

#sf-menu {
  visibility: hidden;
  opacity: 0;
  transition: all .3s;
}
<div id="#sidewidgetarea">
  <a class="closed" href="#sidewidgetarea"
     onclick="with(document.getElementById('sf-menu').style){
              visibility=(visibility==='visible'&&!(opacity=0)&&'hidden')
              ||((opacity=1)&&'visible')}"
     >Switch</a>

  <ul id="sf-menu">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>
Eugene Tiurin
  • 4,019
  • 4
  • 33
  • 32
0

#checkbox1 {
  display:none;
}

#checkbox1:checked ~ .sf-menu {
  visibility: visible;
}

.sf-menu {
  visibility:hidden;
}

.pseudo-link {
  cursor: pointer;
}
<div>
  <input type="checkbox" id="checkbox1">
  <label for="checkbox1"" class="pseudo-link>The link</label>
  <ul class="sf-menu">
     <li> item 1</li>
     <li> item 2</li>
     <li> item 3</li>
  </ul>
</div>

No javascript required. The label will be treated as if it's a link via css.

0

Unfortunately, CSS do not have that feature yet.

JQuery can done for you, in two lines of code.

$('.button').click(function(){
   $('.sf-menu').toggle();
});
7urkm3n
  • 6,054
  • 4
  • 29
  • 46