最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Toggle sidebar div with another div using CSSJavascript - Stack Overflow

programmeradmin3浏览0评论

here's my situation:

So I'm trying to toggle a sidebar by clicking another div. It's a 100% height sidebar that is fixed to the right side of the viewport. Essentially I am trying to wrap a 300px div around both the 50px wide toggle div and the 250px wide sidebar div, and I want to hide the sidebar portion using a negative margin-right pixel value. Using the .toggle:active selector (so this occurs when the toggle div is clicked), I want to show the sidebar portion by setting that margin-right pixel value back to 0px.

Code so far:

<div class="wrapper">
  <a href="#">
    <div class="toggle">Toggle</div>
  </a>
  <div class="cart">Cart</div>
</div>

CSS so far:

.wrapper {
  position:fixed;
  width:300px;
  height:100%;
  background-color:orange;
  top:0;
  right:0;
  margin-right:-250px;
}
.toggle {
  position:relative;
  display:block;
  width:50px;
  height:100%;
  background-color:grey;
  float:left;
}
.toggle:active .wrapper {
  margin-right:0px;
}
.cart {
  position: relative;
  width:250px;
  height:100%;
  background-color:red;
  float:right;
}

Here's the jsfiddle!

Here's my question:

How can I target .wrapper to change a css attribute when .toggle:active is engaged? Also, how can I specify when the sidebar is visible and when it's not?

I'm new to Javascript, but it seems like I'll need it to do this due to the callback function. If CSS-only is possible, I'd lean toward that solution. Please note that I want to use margin-right so that I can opt to use CSS transitions later to animate my element sliding left and right.

here's my situation:

So I'm trying to toggle a sidebar by clicking another div. It's a 100% height sidebar that is fixed to the right side of the viewport. Essentially I am trying to wrap a 300px div around both the 50px wide toggle div and the 250px wide sidebar div, and I want to hide the sidebar portion using a negative margin-right pixel value. Using the .toggle:active selector (so this occurs when the toggle div is clicked), I want to show the sidebar portion by setting that margin-right pixel value back to 0px.

Code so far:

<div class="wrapper">
  <a href="#">
    <div class="toggle">Toggle</div>
  </a>
  <div class="cart">Cart</div>
</div>

CSS so far:

.wrapper {
  position:fixed;
  width:300px;
  height:100%;
  background-color:orange;
  top:0;
  right:0;
  margin-right:-250px;
}
.toggle {
  position:relative;
  display:block;
  width:50px;
  height:100%;
  background-color:grey;
  float:left;
}
.toggle:active .wrapper {
  margin-right:0px;
}
.cart {
  position: relative;
  width:250px;
  height:100%;
  background-color:red;
  float:right;
}

Here's the jsfiddle!

Here's my question:

How can I target .wrapper to change a css attribute when .toggle:active is engaged? Also, how can I specify when the sidebar is visible and when it's not?

I'm new to Javascript, but it seems like I'll need it to do this due to the callback function. If CSS-only is possible, I'd lean toward that solution. Please note that I want to use margin-right so that I can opt to use CSS transitions later to animate my element sliding left and right.

Share Improve this question asked Jan 22, 2013 at 1:56 Betafresh MediaBetafresh Media 1871 gold badge2 silver badges11 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 4

CSS Only Solution

DEMO: http://jsfiddle/Victornpb/yJYJC/30/

Just use this:

/* Closed */
.wrapper{
    margin-right:-250px; 
}

/* Opened */
.wrapper:hover{
    margin-right:0px;
}

Javascript solution

DEMO: http://jsfiddle/Victornpb/yJYJC/6/

JS:

var wrapper = document.getElementsByClassName('wrapper')[0];
var toggle = document.getElementsByClassName('toggle')[0];

window.onload=function(){

    toggle.onclick=function(){
        wrapper.classList.toggle('opened'); 
    }

}

CSS:

.wrapper{
    position:fixed;
    width:300px;
    height:100%;
    background-color:orange;
    top:0;
    right:0;
    margin-right:-250px;
}
.wrapper.opened{
    margin-right:0px;
}

A CSS-only solution (DEMO):

<div class="wrapper">    
  <label for="toggle">
     Toggle
  </label>    
  <input id="toggle" type="checkbox" />
  <div class="cart">Cart</div>
</div>

(The hidden checkbox is used to determine the toggle state)

#toggle {    
  display:none; /* hide checkbox */
}

/* the label associated with the checkbox (trigger) */
label{
  display:block;
}

/* move the div adjacent to the input (.cart) inside the visible area */
/* when the input is checked */
#toggle:checked ~ .cart{
  right:0;
}

/* the div that's being toggled */
.cart {
  position: absolute;
  width: 250px;
  height: 100%;
  right: -250px;
}

CSS Only, no-js sidebar

two versions with different behaviour

There are two different CSS only animated sidebar:

  1. inspired from @vitim.us, using hover for show / hide
  2. inspired from @niceass, using a hidden checkbox to click for show/hide

Features:

  • Smooth animation
  • Vertical text on sidebar (wich rotate when open)
  • Dynamically resize body while sidebar are moving
  • Clean box for body and sidebar
  • scrollable sidebar content (displaying his scrollbar).

hover (forked from @vitim.us's answer) with some improvements

If not pletely finalized, there is some way to

  • write Open cart / Your cart verticaly
  • suppress newline between Open/Your and cart by using no-breakable space in the CSS.
  • resize main content dynamicaly, while side bar is displaying.

body {
    font-family: sans;
    font-weight: normal;
    font-size: 10pt;
}
.main {
    width: calc( 100% - 3em );
    transition: width ease 1300ms;
}
.wrapper:hover ~ .main {
    width: calc( 100% - 17em );
}
h1 {
    font-weight: bold;
    font-size: 1.3 em;
}
h2 {
    font-weight: bold;
    font-size: 1.15 em;
}
.wrapper{
    position:fixed;
    width: 16em;
    height:100%;
    background-color:orange;
    top:0;
    right:0;
    margin-right:-14em;
    /* Makes opening smoothly */
    transition: margin-right ease 1300ms;
    -moz-transition: margin-right ease 1300ms;
    -webkit-transition: margin-right ease 1300ms;
    -o-transition: margin-right ease 1300ms;
}
.inner {
    position: relative;
    width: 100%;
    float: left;
    display: inline-block;
    transform: rotate(90deg)  translate(-3em,0em);
    transition: transform ease 1300ms;
}

/* opened */
.wrapper.opened,
.wrapper:hover{
    margin-right:0px;
}

.toggle {
  position:relative;
    display:block;
    width:2em;
    height:100%;
    background-color:#CCC;
    float:left;
    font-weight: bold;
    text-align: center;
    padding-top: 50%;
    transition: background-color ease 1300ms;
    transition: color ease 1300ms;
}

/* toggle style when wrapper is hovered */
.wrapper:hover .toggle{
    background-color: #555;
    color: white;
}
.wrapper:hover .toggle .inner{
    transform: rotate(270deg);
}
/* Warn: there is NBSP, not spaces, after Open/Your */
.wrapper:not(:hover) .toggle .inner:before{
    content:"Open";
}
.wrapper:hover .toggle .inner:before{
    content:"Your";
}

.cart {
    position: relative;
    width:13.5em;
    height:100%;
    background-color:rgba(255,255,255,.4);
    float:right;
    padding: .2em;
    overflow: scroll;
}
<div class="wrapper">
    <div class="toggle"><div class="inner">&nbsp;cart</div></div>
    <div class="cart">
        <h2>Cart</h2>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea modo consequat.
       </p>
    </div>
</div>
<div class="main">
<h1>Little <i>no-js</i> css side-bar demo</h1>
<p>This little demo let you see how a side-bar could be done without being using javascript...</p>
 <h2>Lorem Ipsum</h2>   <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea modo consequat.</p>
<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
   </p>

</div>

toggle:checked (forked from @niceass's answer)

Same improvements, but using an invisible checkbox will permit to have to click on (text of) the sidebar to open them and add some other labels where you want to be able to click on.

(This answer is linked to What does "for" attribute do in HTML tag?)

body {
    font-family: sans;
    font-weight: normal;
    font-size: 10pt;
}
#toggle { display:none; }
.main {
    width: calc( 100% - 3em );
    transition: width ease 1300ms;
}
#toggle:checked ~ .main {
    width: calc( 100% - 17em );
}
h1 {
    font-weight: bold;
    font-size: 1.3 em;
}
h2 {
    font-weight: bold;
    font-size: 1.15 em;
}
.wrapper{
    position:fixed;
    width: 16em;
    height:100%;
    background-color:orange;
    top:0;
    right:0;
    margin-right:-14em;
    /* Makes opening smoothly */
    transition: margin-right ease 1300ms;
    -moz-transition: margin-right ease 1300ms;
    -webkit-transition: margin-right ease 1300ms;
    -o-transition: margin-right ease 1300ms;
}
#toggle:checked ~ .wrapper {
    margin-right: 0pt;
}
#but {
    position: relative;
    width: 100%;
    float: left;
    display: inline-block;
    transform: rotate(270deg)  translate(-3em,0em);
    transition: transform ease 1300ms;
}
/* opened */
#zone {
  position:relative;
    display:block;
    width:2em;
    height:100%;
    background-color:#CCC;
    float:left;
    font-weight: bold;
    text-align: center;
    padding-top: 50%;
    transition: background-color ease 1300ms;
    transition: color ease 1300ms;
}

/* toggle style when wrapper is hovered */
#toggle:checked ~ .wrapper #zone {
    background-color: #555;
    color: white;
}
#toggle:checked ~ .wrapper #zone #but {
    color: white;
    transform: rotate(90deg);
}
#toggle:not(checked) ~ .wrapper #zone #but:before {
    content:"Open ";    /* non break space &#160; */
}
#toggle:checked ~ .wrapper #zone #but:before{
    content:"☒ Your ";
}
#toggle:not(checked) ~ .wrapper #zone #but:after {
    content:" ☐";        /* figure space &#8199; */
}
#toggle:checked ~ .wrapper #zone #but:after {
    content:"";
}
.cart {
    position: relative;
    width:13.5em;
    height:100%;
    background-color:rgba(255,255,255,.4);
    float:right;
    padding: .2em;
    overflow: scroll;
}
<input id="toggle" type="checkbox" />  
<div class="wrapper">
    <div id="zone"><label for="toggle" id="but">chart</label></div>
    <div class="cart">
        <h2>Cart</h2>
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea modo consequat.
       </p>
    </div>
</div>
<div class="main">
<h1>Little <i>no-js</i> css side-bar demo</h1>
<p>This little demo let you see how a side-bar could be done without being using javascript. Note that you could toggle sidebar by clicking <a href=''><label for="toggle">[here!]</label></a>...</p>
 <h2>Lorem Ipsum</h2>   <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea modo consequat.</p>
<p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
   </p>

</div>

:active only works for links (i.e. <a> tags), so it can't be used on .toggle, since it's a <div>. Even if you put it on the link, I don't think it'll do what you want though, and there's no way to "target" the parent. Having a <a> surrounding a <div> like that is pretty strange too, you shouldn't need that.

So, you'll need javascript, yes. But you can't really target a class in javascript. You have two solutions:

  1. If you can add an id to the wrapper, you can create a function in javascript that will toggle the state of the sidebar:

    <div class="wrapper" id="myId">
        <a href="#">
            <div class="toggle"
                 onclick="document.getElementById('myId').style.marginRight = (document.getElementById('myId').style.marginRight == '0') ? '-250px' : '0';">Toggle</div>
        </a>
        <div class="cart">Cart</div>
    </div>
    

    Notes: The part (document.getElementById('myId').style.marginRight == '0') ? '-250px' : '0' tests if the margin-right is 0 and if so changes it to -250px and vice versa. What I've done here might not be the best way to do, but I wanted to limit it to something short so you can use it this way, if you don't really understand javascript very well. You will be able to improve it when you'll get to know it better. Also, you will have to put the onclick on every .toggle div you have... You can use event handlers, but I'm pretty sure you don't know what that mean and that might not be a good idea to simply copy-paste this. You can always use the second point for that, since it makes things relatively easy to understand.

  2. If you really want the class (or need to repeat this a lot), you will have to use jQuery, a javascript library, by adding this (preferably in the <head>):

    <script type="text/javascript" src="http://code.jquery./jquery-1.9.0.min.js"></script>
    

    Then you can add this (to the head preferably still):

    <script type="text/javascript">
        $(document).ready( function()
        {
            var cart_visible = false;
    
            $('.toggle').on('click', function()
            {
                if ( cart_visible )
                    $('.wrapper').css('margin-right', '-250px');
                else
                    $('.wrapper').css('margin-right', '0');
    
                cart_visible = !cart_visible;
            });
        });
    </script>
    

    This time I used a boolean (that takes true or false as a value) to check if the cart was visible or not, changing the value at each click at the same time as the margin-right. This does the same thing as before, just toggles between -250px and 0, but you don't need to put it in every .toggle you might create and it works with a class. It makes you use jQuery though (that's not really a problem though I think)

I don't really see why you want to change margin-right though... If you just want to make it disappear, you can use display: none;, or if you really want to change the position, you can use right (in this case).

I would remend using jQuery for this. It is simple and less chance for errors.

$('.toggle').click(function() {
    $('.cart').toggle();
});

http://api.jquery./toggle/

发布评论

评论列表(0)

  1. 暂无评论