1

I've got a group of divs like so:

<div id="container">
    <div id="tabs">
        <div class="row"><div class="tab">....</div></div>
        ...
    </div>
</div>

with the following css:

#container {
    position:absolute;
    top:48px;
    bottom:0px;
    width:100%;
}
#tabs {
    display:table;
    height:100%;
}
.row {
    display:table-row;
}
.tab {
    display:table-cell;
    text-align:center;
    vertical-align:middle;
}

This creates a group of element all the same height vertically down the left side of my area. The problem is, I want the .tabs to be square. Since the tabs are dynamically sized to fit the vertical space, I can't define a width. How can I make the width match the height? Ideally this should be done without JavaScript, and pure css/html.

Here's a fiddle as requested.

sharf
  • 2,123
  • 4
  • 24
  • 47
  • if you can share a fiddle with us, it would be helpfull.. – Lal May 03 '15 at 17:15
  • @Lal Just a copy paste of my question, but I updated my question with a fiddle. – sharf May 03 '15 at 17:19
  • 2
    Have a look at this: http://stackoverflow.com/questions/13851940/pure-css-solution-square-elements. – garryp May 03 '15 at 17:40
  • @garryp Thanks for the link, I've used a similar method elsewhere in my app. Unfortunately it seems that `display:table-cell` prevents this kind of method from working. – sharf May 03 '15 at 17:50
  • If your squares' sizes are fixed relative to viewport size, you can use the CSS3 units `vh` and `vw`. Otherwise, you might try the [image holder trick](http://stackoverflow.com/a/13852277/2908724). – bishop May 04 '15 at 02:28

3 Answers3

1

See this fiddle

I've used a simple JS as below

<script>
    var th = $('.tab').height();
    $('.row').css({'width':th+'px'});
</script>

Please note that this <script> should be loaded in document.ready only after the body has loaded.

Lal
  • 14,726
  • 4
  • 45
  • 70
  • This does not meet any of the conditions from my question. The `display:table-row` is to complete the table functionality. I want the `.tab`s to be equal height and fill the entire height of the parent. – sharf May 03 '15 at 17:33
  • Is [this](http://jsfiddle.net/toe55dyr/2/) what you need? It includes `display:table-row` – Lal May 03 '15 at 17:40
  • Yes that accomplishes what I'm looking for, though it's a solution I'm already aware of. As stated in my question, I would rather use a css/html approach if possible. – sharf May 03 '15 at 17:42
  • Since it does not satisfy the requirements in the question I'm not going to upvote. – sharf May 03 '15 at 17:47
  • Do you mean you are working on another answer? Or that this answer is using css? – sharf May 03 '15 at 17:52
  • Great! If you make any progress with it, please update your answer and I'll gladly upvote, and if it works, accept it. – sharf May 03 '15 at 17:55
1

If you can do away for the 48px position from top, you can use this solution:

body {
  margin: 0;
}

#container {
  bottom: 0;
  position: absolute;
  width: 100%;
}

.row {
  padding-bottom: 14.28571429%;
  position: relative;
  width: 14.28571429%;
}

.tab {
  bottom: 0;
  font-size: 20px;
  height: 20px;
  left: 0;
  margin: auto;
  position: absolute;
  right: 0;
  top: 0;
}

Explanation

It leverages the fact that padding is bound to the width of the element it's attached to. You make the outer element .row square by this, using 1/7th of the available screen size in height. By setting a position on the outer element and the inner .tab to position: absolute, you can also use a nifty trick by setting margin: auto along with top, right, bottom and left to 0. You need to specify a height for this element for it to work. Hence the font-size and corresponding height, assuming you only need to center one line of text. By adjusting the height, you can fine tune possible off-positioning caused by a fonts' baseline shift.

herrbischoff
  • 3,294
  • 1
  • 29
  • 50
  • When using the provided CSS, the height of the elements scale with the width, so a wider resolution shows the first tabs off screen to the top, while thin resolutions have all tabs on the bottom 50% of the viewport. – sharf May 03 '15 at 22:14
  • You're right. I have quickly thrown this together without testing it properly. Thinking a little more on this, I believe you will have no way to avoid using JavaScript for this task as you want both dimensions to adjust automatically to whichever way you scale the browser window. – herrbischoff May 03 '15 at 22:47
  • I've managed to accomplish what I want with CSS, but there are some issues (with chrome at least) that cause it to be buggy and unpredictable. I think you're right, unfortunately. – sharf May 03 '15 at 22:52
  • If you feel that my answer helped you, you could [accept my answer](http://meta.stackexchange.com/a/5235). – herrbischoff Jul 10 '17 at 19:18
1

I have tinkered with the idea and here's what I have come up with, for what it's worth. As written in a previous comment, I do not believe there is a CSS only solution. However, the JS required is minimal.

HTML

<div id="container">
  <div id="tabs">
    <div class="row">
      <div class="tab"><span>1</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>2</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>3</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>4</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>5</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>6</span></div>
    </div>
    <div class="row">
      <div class="tab"><span>7</span></div>
    </div>
  </div>
</div>

CSS

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
}
#container {
  width: 100%;
  height: 100%;
}
#tabs {
  width: 100%;
  height: 100%;
}
.row {
  position: relative;
  height: 14.28571429%;
}
.tab {
  display: block;
  position: relative;
  background-color: #008000;
}
.tab span {
  position: absolute;
  height: 20px;
  font-size: 20px;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  text-align: center;
}

JS

var adjustHeight = function() {

  var rowHeight = $('.row').height();
  $('.tab').each(function(){
    $(this).height(rowHeight);
    $(this).width(rowHeight);
  });

}

adjustHeight();

$(window).on("resize", function() {
  adjustHeight();
});

In case you want to play around with it, I have created a Codepen: http://codepen.io/anon/pen/WvvWPE

Update: I have edited the Codepen to calculate the height of the rows automatically instead of setting it via CSS.

herrbischoff
  • 3,294
  • 1
  • 29
  • 50