Wie kann ein Inline-Block-Element den Rest der Zeile ausfüllen?

185

Ist so etwas mit CSS und zwei Inline-Block-DIV-Tags (oder was auch immer) möglich, anstatt eine Tabelle zu verwenden?

Die Tabellenversion lautet wie folgt (Rahmen hinzugefügt, damit Sie sie sehen können):

<!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>

Es wird eine linke Spalte mit einer FESTEN BREITE (keine prozentuale Breite) und eine rechte Spalte erstellt, die erweitert wird, um den verbleibenden Bereich in der Zeile auszufüllen . Klingt ziemlich einfach, oder? Da außerdem nichts "schwebt", wird die Höhe des übergeordneten Containers ordnungsgemäß erweitert, um die Höhe des Inhalts zu erfassen.

--BEGIN RANT--
Ich habe die Implementierungen "Clear Fix" und " Holy Grail " für mehrspaltige Layouts mit seitlicher Spalte mit fester Breite gesehen, und sie saugen und sind kompliziert. Sie kehren die Reihenfolge der Elemente um, verwenden prozentuale Breiten oder verwenden Gleitkommazahlen, negative Ränder, und die Beziehung zwischen den Attributen "links", "rechts" und "Rand" ist komplex. Darüber hinaus sind die Layouts subpixelempfindlich, sodass durch Hinzufügen eines einzelnen Pixels mit Rändern, Auffüllungen oder Rändern das gesamte Layout unterbrochen und ganze Spalten in die nächste Zeile umgebrochen werden. Zum Beispiel sind Rundungsfehler ein Problem, selbst wenn Sie versuchen, etwas Einfaches zu tun, z. B. 4 Elemente in eine Linie zu setzen, wobei die Breite jedes Elements auf 25% festgelegt ist.
--END RANT--

Ich habe versucht, "Inline-Block" und "White-Space: Nowrap;" zu verwenden, aber das Problem ist, dass ich das zweite Element nicht dazu bringen kann, den verbleibenden Platz in der Zeile zu füllen . Das Festlegen der Breite auf "width: 100% - (LeftColumWidth) px" funktioniert in einigen Fällen, aber das Durchführen einer Berechnung in einer width-Eigenschaft wird nicht wirklich unterstützt.

Triynko
quelle
1
Ich denke nicht, dass es einen vernünftigen Weg gibt, dies zu tun, außer dies in ein display: table-*Konstrukt umzuwandeln, das funktionieren wird, aber auch nicht wirklich "semantischer" ist (ein schrecklicher Fall von divSuppe) und die IE6-Kompatibilität bricht. Ich persönlich würde mich an die halten <table>, es sei denn, jemand schafft es, eine geniale, einfache Idee zu entwickeln, die ohne funktioniert
Pekka
51
Ja. Ich stoße seit Beginn des CSS-Zeitalters immer wieder auf all diese Argumente zum Vermeiden von Tabellen. Sie sind so formuliert, dass Sie wie ein inkompetenter fauler Idiot klingen, wenn Sie immer noch Tabellen für Layouts verwenden. Ein Jahrzehnt schneller Vorlauf, und es ist immer noch ein idealistischer Wunschtraum. Tatsache ist, dass die Flow-Layout-Semantik für feste, aber flexible Layouts wie Benutzeroberflächen und Formulare SUCK ist. Die Wahrheit ist, dass kluge Leute Tabellen verwenden, wo es bequem ist, weil sie jede mögliche CSS-Lösung ausgeschöpft haben und erkannt haben, dass sie alle unvollkommen und wesentlich komplexer sind als nur die Verwendung einer Tabelle.
Triynko
4
Schwimmt? Zeigen Sie mir Arbeitscode, bei dem Zeilenendelemente nicht unvorhersehbar umbrochen werden und Ränder und Ränder das Layout nicht beschädigen. Das ist was mit ihnen los ist. Wird der übergeordnete Container mit der automatischen Größe ordnungsgemäß erweitert, um schwebende Elemente ohne die "Clear Fix" -Hacks einzuschließen? Das habe ich nicht gedacht.
Triynko
Wenn Sie mindestens ein nicht schwebendes Element in Ihrem übergeordneten Container haben, ist es nicht wirklich ein "Hack", um Floats zu löschen, oder? Denken Sie daran, dass CSS seine Wurzeln im Drucken hat. Unter css-tricks.com/containers-dont-clear-floats finden Sie eine gute Diskussion darüber, warum Sie kein automatisches Löschen erhalten.
Chowlett
3
@Triynko: Das habe ich früher gemacht: jsfiddle.net/thirtydot/qx32C - Ich denke, es trifft die meisten Ihrer Punkte. Ich werde Ihre Kritik an dieser Demo hören und versuchen, sie anschließend zu beheben.
dreißig Punkte

Antworten:

169

Siehe: 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>


Warum hat ersetze ich margin-left: 100pxmit overflow: hiddenauf .right?

EDIT: Hier sind zwei Spiegel für den obigen (toten) Link:

dreißig Punkte
quelle
60
Wenn Sie sich als Webentwickler bezeichnen, müssen Sie auf diesen Link klicken. Ich tat es und fühlte mich wie Jasmine auf einem Zauberteppich.
Chris Shouts
2
@ ChrisShouts, das ist wahrscheinlich der beste Weg, dies zu beschreiben. Diese Methode macht einfach keinen Sinn, aber andererseits ... Eine wunderbare Problemumgehung für etwas, das Sie explizit tun sollten.
mjvotaw
14
Überlauf versteckt ist keine Lösung. Angenommen, Sie möchten nicht, dass der Überlauf des richtigen Containers ausgeblendet wird. Dadurch füllt die Größe des richtigen Containers nicht den verbleibenden Platz in der Zeile. Dies ist ein Beispiel für eine zwei Jahre alte Frage, für die ich noch keine Antwort markiert habe, da es immer noch keine zufriedenstellende Antwort gibt.
Triynko
3
Triynko: Auch wenn Sie "Überlauf: versteckt" verwenden, wird im Allgemeinen nichts versteckt (zumindest, wenn Sie nur Text darin haben). Der Text / die Elemente innerhalb des Div werden so angeordnet, dass sie in das Div passen (es sei denn, Sie haben ein Element, das natürlich größer als das Div ist).
CpnCrunch
1
@RMorrisey: Benötigt wahrscheinlich nur einige box-sizing: border-boxauf dem divs. Nur eine Vermutung, da Sie keine Demo zur Verfügung gestellt haben, die das von Ihnen beschriebene Verhalten zeigt. That being said, die display: tableist -basierte Lösung in der Regel besser . Dies ist eine sehr alte Frage, aber ich glaube, ich habe versucht, aufgrund des Verhaltens von OP alles zu vermeiden, was mit Tabellen in dieser Frage zu tun hat.
30.
63

Eine moderne Lösung mit 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/

Panu Horsmalahti
quelle
4
Anzeige Flex und Breite 100% .. muss sich erinnern
dreamerkumar
9
Warum nicht flex: 1statt Flex verwenden width: 100%?
Itai Bar-Haim
Für diejenigen, die neu in der Flexbox sind : flex: 1ist eine Abkürzung für flex-grow: 1. Es ist ein Kombinationsattribut : flex: <grow> <shrink> <basis>.
Tanius
1
Nur eine kurze Anmerkung, dass Anzeige: Flex wird in IE <11 nicht unterstützt und in 11 sehr fehlerhaft.
Eric Shields
1
@EricShields Dies sollte niemanden daran hindern, Flexbox zu verwenden. Heutzutage haben wir flexbugsSie wissen.
Neurotransmitter
47

Kompatibel mit herkömmlichen modernen Browsern (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>

Frosty Z.
quelle
9
Das Argument gegen die Verwendung von Tabellen hat nichts mit den Darstellungsmerkmalen zu tun. Dies hat mit nicht verwaltbarem Markup, Durcheinander von Stilen / Dokumenten und falscher Semantik zu tun. Keines dieser Argumente trifft zu display:table.
Rich Remer
Dies beantwortet nicht, wie inline-blockder Rest der Zeile ausgefüllt werden soll.
Neurotransmitter
1
@TranslucentCloud Ich stimme zu, dass meine Antwort den Fragentitel nicht genau beantwortet, aber eine Möglichkeit bietet, die verfügbare Breite mithilfe von divs zu füllen, wie im Fragetext angegeben.
Frosty Z
1
Ich mag diese Lösung sehr. Sie müssen keine seltsamen Stile verwenden, die sich aus der verborgenen CSS-Logik ergeben (wie bei verstecktem Überlauf).
Chaoste
4

Sie können calc (100% - 100px) für das Fluidelement zusammen mit display: inline-block für beide Elemente verwenden.

Beachten Sie, dass zwischen den Tags kein Leerzeichen stehen darf, da Sie dieses Leerzeichen sonst auch in Ihrer Berechnung berücksichtigen müssen.

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


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

Kurzes Beispiel: http://jsfiddle.net/dw689mt4/1/

SuperIRis
quelle
1

Ich habe flex-growEigentum verwendet, um dieses Ziel zu erreichen. Sie werden zum Satz haben display: flexfür übergeordnete Container, dann müssen Sie Satz flex-grow: 1für den Block Sie verbleibenden Raum füllen wollen, oder einfach nur flex: 1als tanius in den Kommentaren erwähnt.

Vladislav Kovechenkov
quelle
0

Wenn Sie CSS-Hacks / Workarounds nicht verwenden können overflow: hidden(weil Sie dies nicht möchten overflow: hidden) oder nicht mögen, können Sie stattdessen JavaScript verwenden. Beachten Sie, dass es möglicherweise nicht so gut funktioniert, da es sich um JavaScript handelt.

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/

Nick Manning
quelle