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

javascript - Vertically Stretch List Items - Stack Overflow

programmeradmin8浏览0评论

I am building a phonegap application. I have the following:

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Three <br>a Half</li>
</ul>

How can I make the <li> elements stretch vertically and fill the whole height of the page given that this needs to be dynamic so that it adapts to other viewports. The text inside the <li> elements needs to be vertically centred and supports multiple lines.

Is there any clean way of doing this?

I am building a phonegap application. I have the following:

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Three <br>a Half</li>
</ul>

How can I make the <li> elements stretch vertically and fill the whole height of the page given that this needs to be dynamic so that it adapts to other viewports. The text inside the <li> elements needs to be vertically centred and supports multiple lines.

Is there any clean way of doing this?

Share Improve this question asked Dec 31, 2014 at 4:01 user1027620user1027620 2,7856 gold badges40 silver badges69 bronze badges 4
  • First you say stretch, then you say vertically centered. Which one do you want? – David Commented Dec 31, 2014 at 4:11
  • 1 @David both, the <li> vertically stretched to fit the viewport and the content inside the <li> vertically centred and supports multi-lines. – user1027620 Commented Dec 31, 2014 at 4:13
  • 1 does phonegap play well with display: table-cell? If it does this might work: jsfiddle/6z3q35x0/1 – Joseph Marikle Commented Dec 31, 2014 at 4:34
  • @JosephMarikle I think it does. – user1027620 Commented Dec 31, 2014 at 4:50
Add a ment  | 

5 Answers 5

Reset to default 6

I suggest using the display: table family of CSS3 rules. They'll be dynamic and maintain full height spacing if done correctly:

body, html {
    height: 100%;
    margin: 0;
}

ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    display: table;
    width: 100%;
    height: 100%;
}

ul li {
    display: table-row;
}

ul li a { /* assuming an anchor child.  Can be anything */
    display: table-cell;
    vertical-align: middle;
    padding: 1em 3em;
}

Demo: http://jsfiddle/6z3q35x0/1/

There are two parts to your question: the first is to force the <ul> element to stretch to fill the viewport, and the second is to vertically and horizontally center the <li> content. However, the centering requires modifications to your markup. We can wrap all the content in <li> using <div> elements.

For centering, we can use CSS3 flexbox for that. This would be a JS-free solution, although it enjoys less cross-browser support. For viewport size, we can use the vw and vh units respectively.

ul {
  display: flex;
  flex-direction: column;
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
}
li {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-grow: 1;
}
li div {
  
}

/* For stylistics only */
li:nth-child(odd) {
  background-color: #ddd;
}
<link href="http://cdnjs.cloudflare./ajax/libs/normalize/3.0.2/normalize.min.css" rel="stylesheet"/>
<ul>
<li><div>One</div></li>
<li><div>Two</div></li>
<li><div>Three</div></li>
<li><div>Three <br>a Half</div></li>
</ul>


However, there might be situations where using CSS flexbox and viewport units are not ideal — iOS7, for example, has a well-documented rendering bug that does not calculate vh properly. In this case, we might have to rely on JS instead. The height of each <li> is simply divided by the number of <li>s present in the container.

var calcHeight = function() {
  var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

  var li = document.querySelectorAll("ul li");
  for(var i=0; i<li.length; i++) {
    li[i].style.height = (h/li.length)+'px';
  }
}

calcHeight();
window.onresize = calcHeight();
ul {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100vh;
}
li {
  display: block;
  width: 100%;
  position: relative;
}
li div {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

li:nth-child(odd) {
  background-color: #ddd;
  }
<link href="http://cdnjs.cloudflare./ajax/libs/normalize/3.0.2/normalize.min.css" rel="stylesheet"/>
<ul>
  <li><div>One</div></li>
  <li><div>Two</div></li>
  <li><div>Three</div></li>
  <li><div>Three <br>a Half</div></li>
</ul>

Here is a JavaScript solution, which will give the heights according to the viewport's height.

Forcing ul to take the entire viewport's height:

Demo on Fiddle

var li = document.getElementsByTagName('li');
function doMath() {
  for (i = 0; i < li.length; i++) {
    li[i].style.height = window.innerHeight / li.length + 'px';
  }
}
doMath();
window.onresize = doMath;
ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
li {
  background: rosybrown;
}
span {
  display: block;
  position: relative;
  top: 50%;
  text-align: center;
  transform: translateY(-50%);
}
li:nth-of-type(2n) {
  background: plum;
}
body {
  margin: 0;
}
<ul>
  <li><span>One</span></li>
  <li><span>Two</span></li>
  <li><span>Three</span></li>
  <li><span>Three<br />a Half</span></li>
  <li><span>Four</span></li>
  <li><span>Five<br />a Half</span></li>
  <li><span>Six</span></li>
</ul>


Forcing lis to take the entire viewport's height:

Demo on Fiddle

var li = document.getElementsByTagName('li');
function doMath() {
  for (i = 0; i < li.length; i++) {
    li[i].style.height = window.innerHeight + 'px';
  }
}
doMath();
window.onresize = doMath;
ul {
  padding: 0;
  margin: 0;
  list-style: none;
}
li {
  background: rosybrown;
}
span {
  display: block;
  position: relative;
  top: 50%;
  text-align: center;
  transform: translateY(-50%);
}
li:nth-of-type(2n) {
  background: plum;
}
body {
  margin: 0;
}
<ul>
  <li><span>One</span></li>
  <li><span>Two</span></li>
  <li><span>Three</span></li>
  <li><span>Three<br />a Half</span></li>
  <li><span>Four</span></li>
  <li><span>Five<br />a Half</span></li>
  <li><span>Six</span></li>
</ul>

You need to add height 100% to body and html, try this

<style>
body, html {
  height: 100%;
}
ul {
    height: 100%;
    display: table;
}
li {
   height: 25%;
    display: table-row;
}
li div{
    height: 25%;
    display: table-cell;
    vertical-align: middle;
}
</style>

Jsfiddle link: http://jsfiddle/d80xw55e/1/

Since you're allowing Javscript, this is pretty easy, I'm just having trouble getting the bullet point right. Hopefully you won't be using that though?

function liH(){
  var lis = document.getElementsByTagName("li");
  var spans = document.getElementsByTagName("span");
  var liHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) / lis.length;
  
  for(var i = 0; i < lis.length; ++i){
    var spanH = spans[i].getBoundingClientRect().height;
    lis[i].style.paddingTop = ((liHeight - spanH) / 2) + "px";
    lis[i].style.paddingBottom = lis[i].style.paddingTop;
    //spans[i].style.top = -(spanH / 4) + "px"
  }
}

liH();
window.onresize = liH;
li {background:#eee;margin-bottom:5px;}
span {position:relative;}
<ul>
  <li><span>elem1</span></li>
  <li><span>elem2</span></li>
  <li><span>elem<br />3</span></li>
</ul>

The reason the view is not exact is because of the padding on the top that won't remove, and because of the 5px margin which I put to distinguish the elements.

发布评论

评论列表(0)

  1. 暂无评论