user610217
user610217

Reputation:

Overlapping stackable, clickable shapes with CSS and/ or JavaScript?

This is going to be difficult for me to describe, so please bear with me.

I have a requirement to build an "upvote" control for a website. The number of "upvotes" is configurable in the system settings. The controls are supposed to look like green chevrons pointing up. If there are three, if you click on the top one, you have effectively "voted" with a weight of 3. If you subsequently click on the bottom chevron, you are effectively changing your vote weight to 1. There's also hover, click, and active styling associated with the vote chevrons.

The wireframes show these chevrons pretty closely stacked, to the point where the upper point of the bottom chevron is higher than the bottom point of the top chevron in my 3-vote example.

This sorta precludes me using images, as overlap would be a difficult experience to manage, I think. So I'm hoping there is a relatively straightforward way to "build" these shapes using CSS and/ or JavaScript and treat them as standard divs.

Am I in trouble? Or is there a relatively straightforward way to do this that is compatible with all modern browsers (IE 9+)?

Upvotes: 0

Views: 688

Answers (2)

Persijn
Persijn

Reputation: 15000

Svg chevrons

If you create this shape with svg, each shape has it own borders. So with hover statments will only be trigger inside its a shape.
For the click, i added javascript and id's to each of the shapes.

var down1 = document.getElementById("down1");
var down2 = document.getElementById("down2");
var down3 = document.getElementById("down3");
var up1 = document.getElementById("up1");
var up2 = document.getElementById("up2");
var up3 = document.getElementById("up3");

function pling() {
  alert(this.id);
}

down1.addEventListener("click", pling);
down2.addEventListener("click", pling);
down3.addEventListener("click", pling);
up1.addEventListener("click", pling);
up2.addEventListener("click", pling);
up3.addEventListener("click", pling);
#center {
  fill: #222;
  stroke: #bbb;
  stroke-width: 0.5;
}
.up {
  fill: #5a5;
  cursor: pointer;
}
.up:hover {
  fill: #262;
  stroke: green;
  stroke-width: 0.1;
}
.down {
  fill: #322;
  cursor: pointer;
}
.down:hover {
  fill: #a55;
  stroke: red;
  stroke-width: 0.1;
}
<svg viewBox="0 0 50 100" width="100px" xmlns="http://www.w3.org/2000/svg">
  <polygon id="center" points="5,50 25,30 45,50, 25,70 5,50" />
  <polygon id="down3" class="down" points="5,70 25,90 45,70 45,80 25,100 5,80" />
  <polygon id="down2" class="down" points="45,60 25,80 5,60 5,70 25,90 45,70" />
  <polygon id="down1" class="down" points="5,50 25,70 45,50 45,60 25,80 5,60" />
  <polygon id="up1" class="up" points="5,50 25,30 45,50 45,40 25,20 5,40" />
  <polygon id="up2" class="up" points="5,40 25,20 45,40 45,30 25,10 5,30" />
  <polygon id="up3" class="up" points="5,30 25,10 45,30 45,20 25,0 5,20" />
</svg>

Upvotes: 0

LOTUSMS
LOTUSMS

Reputation: 10270

This will give you the front end side started. At least a direction on where to go from there. With some JS and back-end programming you'll be able to make those font awesome icons register the value of 1, 2, or 3

HTML

<div class="container">
    <div class="rating">
        <div class="upvote">
            <div><i class="fa fa-chevron-up"></i></div>
            <div><i class="fa fa-chevron-up"></i></div>
            <div><i class="fa fa-chevron-up"></i></div>
        </div>
        <span class="divider"></span>
        <div class="downvote">
            <div><i class="fa fa-chevron-down"></i></div>
            <div><i class="fa fa-chevron-down"></i></div>
            <div><i class="fa fa-chevron-down"></i></div>
        </div>
    </div>
</div>

CSS

.rating{
    margin-top:30px;
}
.rating > div {
  position: relative;
  width: 1.1em;
  margin:-10px auto;
}

.rating .fa{
    font-size:32px;
    line-height: 0;
}
.rating .divider{
    width:40px;
    display:block;
    border-bottom: 3px solid black;
    height:5px;
    text-align:center;
    margin: 15px 458px 25px;

}
.upvote > div .fa-chevron-up:hover,
.upvote > div:hover ~ div .fa-chevron-up {
   color: green;
}

.downvote > div .fa-chevron-down:hover,
.downvote > div:hover ~ div .fa-chevron-down {
   color: red;
}

p.s. As you may already know, CSS doesn't traverse, therefore you'll need some help assigning hover attributes to the downvote section. If no one else has this answer by tomorrow, I'll build it for you.

Here's the DEMO

Upvotes: 1

Related Questions