开发者

How to make an inline-block element fill the remainder of the line?

Is such a thing possible using CSS and two inline-block (or whatever) DIV tags instead of using a table?

The table version is this (borders added so you can see it):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<table style="width:100%;">
<tr>
<td style="border:1px solid black;width:100px;height:10px;"></td>
<td style="border:1px solid black;height:10px;"></td>
</tr>
</table>
</body>
</html>

It produces a left column with a FIXED WIDTH (not a percentage width), and a right column that expands to fill THE REMAINING SPACE on the line. Sounds pretty simple, right? Furthermore, since nothing is "floated", the parent container's height properly expands to encompass the height of the content.

--BEGIN RANT--

I've seen the "clear fix" and "holy grail" implementations for multi-column layouts with fixed-width side column, and they suck and they're complicated. They reverse the order of elements, they use percentage widths, or they use floats, negative margins, and the relationship between the "left", "right", and "margin" attributes are complex. Furthermore, the layouts a开发者_开发百科re sub-pixel sensitive so that adding even a single pixel of borders, padding, or margins will break the whole layout, and send entire columns wrapping to the next line. For example, rounding errors are a problem even if you try to do something simple, like put 4 elements on a line, with each one's width set to 25%.

--END RANT--

I've tried using "inline-block" and "white-space:nowrap;", but the problem is I just can't get the 2nd element to fill the remaining space on the line. Setting the width to something like "width:100%-(LeftColumWidth)px" will work in some cases, but performing a calculation in a width property is not really supported.


See: http://jsfiddle.net/qx32C/36/

.lineContainer {
    overflow: hidden; /* clear the float */
    border: 1px solid #000
}
.lineContainer div {
    height: 20px
} 
.left {
    width: 100px;
    float: left;
    border-right: 1px solid #000
}
.right {
    overflow: hidden;
    background: #ccc
}
<div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>


Why did I replace margin-left: 100px with overflow: hidden on .right?


A modern solution using flexbox:

.container {
    display: flex;
}
.container > div {
    border: 1px solid black;
    height: 10px;
}

.left {
   width: 100px;
}

.right {
    width: 100%;
    background-color:#ddd;
}
<div class="container">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/m5Xz2/100/


Compatible with common modern browers (IE 8+): http://jsfiddle.net/m5Xz2/3/

.lineContainer {
    display:table;
    border-collapse:collapse;
    width:100%;
}
.lineContainer div {
    display:table-cell;
    border:1px solid black;
    height:10px;
}
.left {
    width:100px;
}
 <div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>


You can use calc (100% - 100px) on the fluid element, along with display:inline-block for both elements.

Be aware that there should not be any space between the tags, otherwise you will have to consider that space in your calc too.

.left{
    display:inline-block;
    width:100px;
}
.right{
    display:inline-block;
    width:calc(100% - 100px);
}


<div class=“left”></div><div class=“right”></div>

Quick example: http://jsfiddle.net/dw689mt4/1/


I've used flex-grow property to achieve this goal. You'll have to set display: flex for parent container, then you need to set flex-grow: 1 for the block you want to fill remaining space, or just flex: 1 as tanius mentioned in the comments.


If you can't use overflow: hidden (because you don't want overflow: hidden) or if you dislike CSS hacks/workarounds, you could use JavaScript instead. Note that it may not work as well because it's JavaScript.

var parent = document.getElementsByClassName("lineContainer")[0];
var left = document.getElementsByClassName("left")[0];
var right = document.getElementsByClassName("right")[0];
right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
window.onresize = function() {
  right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
}
.lineContainer {
  width: 100% border: 1px solid #000;
  font-size: 0px;
  /* You need to do this because inline block puts an invisible space between them and they won't fit on the same line */
}

.lineContainer div {
  height: 10px;
  display: inline-block;
}

.left {
  width: 100px;
  background: red
}

.right {
  background: blue
}
<div class="lineContainer">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/ys2eogxm/


When you give up the inline blocks

.post-container {
    border: 5px solid #333;
    overflow:auto;
}
.post-thumb {
    float: left;
    display:block;
    background:#ccc;
    width:200px;
    height:200px;
}
.post-content{
    display:block;
    overflow:hidden;
}

http://jsfiddle.net/RXrvZ/3731/

(from CSS Float: Floating an image to the left of the text)


If, like me, you want something that will expand to the end of the line even if the left-hand box wraps, then JavaScript is the only option.

I'd make use of the calc feature to get this right:

Array.from(document.querySelectorAll(".right")).forEach((el) => {
  el.style.width = `calc(100% - ${el.offsetLeft + 1}px)`;
});
.container {
    outline: 1px solid black;
}

.left {
   outline: 1px solid red;
}

.right {
    outline: 1px solid green;
}
<div class="container">
  <span class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tristique aliquet quam, at commodo lorem fringilla quis.</span>
  <input class="right" type="text" />
</div>


A solution using grid layout and fractional units (fr):

/* For debugging and visibility */
html, body {
    border: 2px  solid navy;
}
.grid-layout { 
    border: thick solid sandybrown;
    background-color: gray;
} 
.grid-layout div:nth-child(odd) {
    border: 2px solid brown;
    background-color: azure;
}
.grid-layout div:nth-child(even) {
    border: 2px solid red;
    background-color: lightyellow;
}

/* Grid layout.
 * Horizontal and vertical gaps.
 * two columns, fixed and responsive.
 * Note no containing div per line.
 */
.grid-layout {
    display: grid;
    gap: 4px 2px ;
    grid-template-columns: 100px 1fr;
}
<p>How to make an element fill the remainder of the line?</p>
<p>Note no encompassing div per line.</p>

<div class="grid-layout">
    <div>Lorem ipsum line 1</div>
    <div>Lorem ipsum dolor sit amet,
         consectetur adipiscing elit,
         sed do eiusmod tempor incididunt ut labore
         et dolore magna aliqua.</div>
    <div>Lorem ipsum line 2</div>
    <div>Ut enim ad minim veniam,
         quis nostrud exercitation ullamco laboris
         nisi ut aliquip ex ea commodo consequat.</div>
</div>

A similar solution with encompassing divs:

 .lineContainer {
   display: grid;
   gap: 2px 4px;
   grid-template-columns: 100px 1fr;
 }
<p>Display grid per line.</p>
<div class="lineContainer">
  <div style="border:1px solid black; ">
    Lorem ipsum &hellip;
  </div>
  <div style="border:1px solid black; ">
    Lorem ipsum dolor sit amet,
    consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore
    et dolore magna aliqua.
  </div>
</div>

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜