Question

Please look at the following image:

enter image description here

I'm trying to create the above in CSS, and then use some Javascript so when people click on the circle, it pulls down (i.e.e the chain becomes longer). Next click would pull it back up.

Here is what I have so far, but I'm not sure if I'm on the right path.

http://jsfiddle.net/5CLUg/9/

#pull-chain{    
    display: block;
    position: absolute;
    right: 70px;
    width: 15px;
}
#pull-chain .chain{
    border-left: 2px dotted #333;
    height: 200px;
}   
#pull-chain .handle{
    background-color: #333;
    width:15px;
    height:15px;
    border-radius: 50%;
    position: relative;
    left: -6px;
}

<div id="pull-chain">
    <div class="chain"></div>
    <div class="handle"></div>
</div>

Any idea on how to improve it would be appreciated.

Was it helpful?

Solution

You can just add an event listener for the click event, and use classList.toggle() to add or remove a class. Then for that class you can just adjust the height:

http://jsfiddle.net/5CLUg/5/

var el = document.getElementById("pull-chain");

el.addEventListener("click", function() {
    el.classList.toggle("pulled");
}, false);

CSS:

#pull-chain.pulled .chain {
    height: 350px;
}

If you want it to animate as well you should add the transition property to the original .chain ruleset:

#pull-chain .chain {
    /* removed other declarations for clarity */
    transition: height 0.5s ease-in-out;
}

See it in action: http://jsfiddle.net/5CLUg/8/

As an aside, note that your CSS is very specific with each selector including an ID and having inline styles. Removing those IDs from the selectors would still select the same element and make the code more maintainable. .chain instead of #pull-chain .chain, etc. Then the CSS above could just be .pulled .chain. As it currently stands I need to include the ID in the selector so that it is more specific than the original height property.

OTHER TIPS

Here is an alternate approach to make the entire thing work as expected with just CSS.

In this approach, we use:

  • A check-box which is hidden from view.
  • A label for the check-box which functions as the chain handle.
  • A div which generates the chain.

When the chain handle is clicked, the checked property of the check box is set and we use the :checked property to increase the chain length (and color for some fancy stuff). When the handle is clicked again, the checked property is unset and so the chain goes back to its original state.

The handle (label) is position with respect to the chain (div) and hence there is no need to alter the positioning of the handle on click.

#pull-chain {
  display: none; /* no need to display checkbox */
}
#chain {
  position: relative;
  margin: 0px auto;
  border-right: 2px dotted tomato;
  height: 200px;
  width: 15px;
  -webkit-transition: height 0.5s;
  -moz-transition: height 0.5s;
  transition: height 0.5s;
}
#handle {
  display: block;
  position: absolute;
  /* left: width of chain div (15px) + half of border (1px) - radius of handle (8px)*/  
  left: 8px; 
  bottom: 0%;
  background-color: tomato;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  cursor: pointer
}
#pull-chain:checked + #chain > #handle {
  background-color: seagreen;
}
#pull-chain:checked + #chain {
  height: 250px;
  border-color: seagreen;
}
<input type="checkbox" id="pull-chain" />
<div id="chain">
  <label for="pull-chain" id="handle"></label>
</div>

Just for fun, a pure CSS way to do this: http://jsfiddle.net/xrj5w/6/

<div id="pull-chain">
    <a id="pulled" href="#"></a>
    <a class="unpulled" href="#pulled"></a>
    <div class="chain"></div>
</div>

...
#pull-chain .unpulled {
    z-index: 10; /* makes sure #unpulled is the initial click target */
}
#pull-chain #pulled:target {
    top: 230px;
    z-index: 20; /* after .unpulled is clicked, #pulled becomes the new click target */
}
#pull-chain #pulled:target + .unpulled {
    top: 230px;
}
#pull-chain #pulled:target + .unpulled + .chain {
    height: 230px;
}

http://jsfiddle.net/5CLUg/7/
I think this is what you wanted :D

BTW i totally took this from another post but it seems to work well with your code. CREDIT TO: http://jsfiddle.net/rashomon/8vLQ9/

#pull-chain{    
    display: block;
    position: absolute;
    right: 70px;
    width: 15px;
}
#pull-chain .chain{
    border-left: 2px dotted #333;
    height: 250px;
}   
#pull-chain .handle{
    background-color: #333;
    width:15px;
    height:15px;
    border-radius: 50%;
    position: relative;
    left: -6px;
}    

<body>
<div id="pull-chain"><div class="chain" style="padding-left: 0px; padding-right: 0px; margin-right: 0px;"></div><div class="handle" style="padding-right: 0px; margin-right: 0px;"></div></div>
</body>  

$(document).ready(function() {

    var $handle = $('.handle'),
        $chain = $('.chain'),
        $initHeight = 200; // Initial height

    $chain.each(function() {
        $.data(this, "realHeight", $(this).height());    // Create new property realHeight
        }).css({ overflow: "hidden", height: $initHeight + 'px' });

    $handle.toggle(function() {
          $chain.animate({ height: $chain.data("realHeight") }, 600);          
        }, function() {
            $chain.animate({ height: $initHeight}, 600);
        });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top