Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to make a navigation-div with 4 buttons, one to go left, one to go right, another one to go down and yet another one to go up. Plus there needs to be an OK-button in the middle.

The buttons need to be positions that they form any (the size is not set) rectangle, inside the buttons are positions on the very right, left, top and bottom, and each of them are trapezoids, leaving a square in the middle for the OK-Button.

Just like that: Navbar Element

What I've done is, that I created a trapezoid parent, with position relative shape using css:

.trapezoid_parent {
    position: relative;
}

And a trapezoid to use, which is absolute.

.trapezoid {
    position: absolute;
    border-bottom: 50px solid #f98d12;
    border-left: 80px solid transparent;
    border-right: 80px solid transparent;
    width: 100%; 
    height: 0; 
    z-index: 2;
    border-top: 1px solid #000000;
}

to make the top one, I flip the normal one and position it at the top:

.trapezoid.top {
    transform: rotate(180deg);
    top: 0;
}

the bottom trapezoid just has to be position on the bottom:

.trapezoid.bottom {
    bottom: 0;
}

Next up we need the left button

.left_button {
    height: 100%; 
    position: absolute; 
    width: 40%; 
    left:0; 
    z-index: 1;
    border-right: 1px solid #000000;
}

the one one the right

.right_button {
    height: 100%; 
    position: absolute; 
    width: 40%; 
    right:0; 
    z-index: 1;
    border-left: 1px solid #000000;
}

and last but not least the one in the center:

.center_button {
    height: 100%; position: absolute; width: 100%; right:0; z-index: 0;
}

Then, to put it all together I used the following html:

<div class="trapezoid_parent" style="width:200px; height:125px">
        <button class="left_button function"><i class='fa fa-arrow-left'></i></button>
        <button class="trapezoid top function"><i class='fa fa-arrow-down'></i></button>
        <button class="trapezoid bottom function"><i class='fa fa-arrow-down'></i></button>
        <button class="right_button function"><i class='fa fa-arrow-right'></i></button>
        <button class="center_button">OK</button>
</div>

To make the whole thing responsive I made jQuery plugin which changes the sizes accordingly. It does that, by changing the border-bottom, border-left and border-right properties according to the size of the parent:

var internal_square_size = ((1.0 / 2) - plugin.settings.square_size);

var tpw = $element.width();
var tph = $element.height();
$(".trapezoid", $element)
.css("border-left-width", "" + (tpw * internal_square_size) + "px")
.css("border-right-width", "" + (tpw * internal_square_size) + "px")
.css("border-bottom-width","" + (tph * internal_square_size) + "px");

$(".left_button, .right_button", $element).css("width", "" + internal_square_size*100 + "%");

The result looks like this:

Result

You can view the whole thing here: full jsfiddle example

There are still a few problems and I've spend all my magic already, but maybe someone else has a few ideas how to get the last few pieces.

The diagonal borders can not be displayed using the method presented, which is something I cannot live with. Has anyone an idea?

Second of all: It would be very nice, if the buttons could actually end with the diagonal, because touching a button which is to small is always tough. Am I missing something? Is HTML5 not equipped to do the thing I ask of it?

share|improve this question
7  
Frankly, I'd use an SVG. –  Paulie_D 2 days ago
    
@Paulie_D I thought about that too, but I have never used svg before, could you line out how I would go about doing that as an answer? –  S. van Wickern 2 days ago
1  
That would be very broad and too long to go into here I think but I'll see what I can come up with. –  Paulie_D 2 days ago
    
@Paulie_D thank you, that's exactly what I needed –  S. van Wickern 2 days ago
    
Happy to help. I'm still learning SVG myself. –  Paulie_D 2 days ago

3 Answers 3

up vote 17 down vote accepted

As I mentioned in the comments, I think I would be using an SVG here.

A brief example of the proposed structure.

svg {
  display: block;
  width: 200px;
  height: 200px;
  margin: 25px auto;
  border: 1px solid grey;
  stroke: #006600;
}
#buttons polygon:hover {
  fill: orange;
}
#buttons rect:hover {
  fill: blue
}
#center {
  fill: #00cc00;
}
#top {
  fill: #cc3333;
}
#right {
  fill: #663399;
}
#left {
  fill: #bada55;
}
<svg viewbox="0 0 100 100">
  <g id="buttons">
    <rect id="center" x="25" y="25" height="50" width="50" />
    <polygon id="top" points="0,0 100,0 75,25 25,25" />
    <polygon id="right" points="100,0 75,25 75,75 100,100" />
    <polygon id="bottom" points="0,100 25,75 75,75 100,100" />
    <polygon id="left" points="0,0 25,25 25,75 0,100" />
  </g>
</svg>

Note: As each of the elements inside the SVG has an Id, you should be able to target them with JS/Jquery.

share|improve this answer

The old version is below, it resizes using jQuery. But after looking at this question: SVG polygon points with percentage units support, you can achieve the same effect by applying percentages and without needing any JS:

<div id="svg-container">
    <svg id="mySVG" width='100%' height='100%' viewBox="0 0 100 100" preserveAspectRatio="none" style='background-color: whitesmoke'>
        <polygon id="ok" points="25,25 75,25 75,75 25,75" />
        <polygon id="up" points="0,0 100,0 75,25 25,25" />
        <polygon id="right" points="100,0 100,100 75,75 75,25" />
        <polygon id="down" points="0,100 25,75 75,75 100,100" />
        <polygon id="left" points="0,0 25,25 25,75 0,100" />
    </svg>
</div>

See it working here: http://jsfiddle.net/th4uo8wk/4/


Old answer:

Oops, by the time I had it ready, Paulie_D had come with the answer.

Well, here you have a responsive one (you can see it working on this jsfiddle, resize the screen to see it working responsively):

HTML:

<svg id="mySVG" height="20%" width="20%">
    <polygon id="ok" points="50,50 150,50 150,150 50,150" />
    <polygon id="up" points="0,0 200,0 150,50 50,50" />
    <polygon id="right" points="200,0 200,200 150,150 150,50" />
    <polygon id="down" points="0,200 50,150 150,150 200,200" />
    <polygon id="left" points="0,0 50,50 50,150 0,200" />
</svg>

JS/JQUERY

function resizeButtons() {
    // get the width
    var w = $("#mySVG").width();

    // make it squared
    $("#mySVG").height(w);

    // recalculate the position of each polygon
    $("#ok").attr("points", w * 0.25 + "," + w * 0.25 + " " + w * 0.75 + "," + w * 0.25 + " " + w * 0.75 + "," + w * 0.75 + " " + w * 0.25 + "," + w * 0.75);
    $("#up").attr("points", "0,0 " + w + ",0 " + w * 0.75 + "," + w * 0.25 + " " + w * 0.25 + "," + w * 0.25);
    $("#left").attr("points", w + ",0 " + w + "," + w + " " + w * 0.75 + "," + w * 0.75 + " " + w * 0.75 + "," + w * 0.25);
    $("#down").attr("points", "0," + w + " " + w * 0.25 + "," + w * 0.75 + " " + w * 0.75 + "," + w * 0.75 + " " + w + "," + w);
    $("#right").attr("points", "0,0 " + w * 0.25 + "," + w * 0.25 + " " + w * 0.25 + "," + w * 0.75 + " 0," + w);
}

CSS

svg { background:#ccc; }
#ok { fill: red; }
#up { fill: blue; }
#down { fill: green; }
#right { fill: yellow; }
#left { fill: orange; }
share|improve this answer
    
Thank you, I had the same idea about making it responsive. SVG really is the better option in this case. –  S. van Wickern 2 days ago
    
If you just use a % width on the SVG it's automatically responsive. - codepen.io/Paulie-D/pen/… Not sure you need any JS/JQ. –  Paulie_D 2 days ago
    
@Paulie_D, right. I saw this question stackoverflow.com/questions/17498855/… and updated the code. There's no need for JS to resize –  Alvaro Montoro 2 days ago

As others have already pointed out, you should use SVG for this. Below is a CSS alternative that you may use.

It uses transformed pseudo-elements and transform-origin property. To make it responsive, you need to change the units. As the units are in em in this approach, simply change the font size in the parent, or the body element.

Fiddle

body {
    font-size: 12px;
}
.left, .right, .top, .bottom, .ok {
    height: 10em;
    width: 10em;
    position: relative;
}
.left {
    background-color: #FFBF00;
    margin-top: 10em;
}
.right {
    background-color: #FF7E00;
    margin-top: -10em;
    margin-left: 20em;
}
.top {
    background-color: #D3212D;
    margin-top: -20em;
    margin-left: 10em;
}
.bottom {
    background-color: #318CE7;
    margin-top: 10em;
    margin-left: 10em;
}
.ok {
    background-color: #3B444B;
    margin-top: -21.666em;
    margin-left: 8.333em;
    height: 13.33em;
    width: 13.33em;
}
.ok span {
    line-height: 6.666em;
    text-align: center;
    width: inherit;
    display: block;
    font-size: 2em;
    font-family: sans-serif;
    color: white;
    font-weight: bold;
}
.left:before, .left:after, .right:before, .right:after, .top:before, .top:after, .bottom:before, .bottom:after {
    position: absolute;
    content: "";
    height: inherit;
    width: inherit;
    background-color: inherit;
}
.left:before, .right:before {
    -webkit-transform: skewY(45deg);
    -moz-transform: skewY(45deg);
    -ms-transform: skewY(45deg);
    -o-transform: skewY(45deg);
    transform: skewY(45deg);
}
.top:before, .bottom:before {
    -webkit-transform: skewX(45deg);
    -moz-transform: skewX(45deg);
    -ms-transform: skewX(45deg);
    -o-transform: skewX(45deg);
    transform: skewX(45deg);
}
.left:after, .right:after {
    -webkit-transform: skewY(-45deg);
    -moz-transform: skewY(-45deg);
    -ms-transform: skewY(-45deg);
    -o-transform: skewY(-45deg);
    transform: skewY(-45deg);
}
.top:after, .bottom:after {
    -webkit-transform: skewX(-45deg);
    -moz-transform: skewX(-45deg);
    -ms-transform: skewX(-45deg);
    -o-transform: skewX(-45deg);
    transform: skewX(-45deg);
}
.left:before, .left:after, .bottom:before, .bottom:after {
    -webkit-transform-origin: 100% 0%;
    -moz-transform-origin: 100% 0%;
    -ms-transform-origin: 100% 0%;
    -o-transform-origin: 100% 0%;
    transform-origin: 100% 0%;
}
.right:before, .right:after, .top:before, .top:after {
    -webkit-transform-origin: 0% 100%;
    -moz-transform-origin: 0% 100%;
    -ms-transform-origin: 0% 100%;
    -o-transform-origin: 0% 100%;
    transform-origin: 0% 100%;
}
/*HOVER STYLES*/
.top:hover, .right:hover, .bottom:hover, .left:hover, .ok:hover {background: #F7E7CE; transition: 0.3s ease;}
.ok:hover span {color: #222;}
<div class="left"></div>
<div class="right"></div>
<div class="top"></div>
<div class="bottom"></div>
<div class="ok"><span>OK</span></div>

Screenshot (gif)

enter image description here


Browser support: IE 9+, GC 4+, FF 3.5+, Safari 3.1+, Opera 11.5+

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.