Kann ich verhindern, dass Textfelder mit 100% Breite über ihre Container hinausragen?

180

Nehmen wir an, ich habe ein Textfeld, in das ich eine ganze Zeile einfügen möchte. Ich würde es so gestalten:

input.wide {display:block; width: 100%}

Dies führt zu Problemen, da die Breite auf dem Inhalt des Textfelds basiert. Textfelder haben standardmäßig Ränder, Ränder und Auffüllungen, wodurch ein Textfeld mit einer Breite von 100% größer als sein Container ist.

Zum Beispiel hier rechts:

Geben Sie hier die Bildbeschreibung ein

Gibt es eine Möglichkeit, ein Textfeld dazu zu bringen, die Breite seines Containers zu füllen, ohne darüber hinaus zu expandieren?

Hier ist ein Beispiel-HTML, um zu zeigen, was ich meine:

<!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>
    <title>Untitled Page</title>
    <style type="text/css">
        #outer{border: 1px solid #000; width: 320px; margin: 0px;padding:0px}
        #inner{margin: 20px; padding: 20px; background: #999;border: 1px solid #000;}
        input.wide {display:block; margin: 0px}
        input.normal {display:block; float: right}
    </style>
</head>
<body>
    <div id="outer">
        <div id="inner">
            <input type="text" class="wide" />
            <input type="text" class="normal" />
            <div style="clear:both;"></div>
        </div>
    </div>
</body>
</html>

Wenn dies ausgeführt wird, können Sie anhand des "normalen" Textfelds erkennen, dass das "breite" Textfeld über den Container hinausragt. Das "normale" Textfeld wird an den tatsächlichen Rand des Containers verschoben. Ich versuche, das "breite" Textfeld dazu zu bringen, seinen Container zu füllen, ohne über die Kante hinaus zu expandieren, wie es das "normale" Textfeld ist.

Dan Herbert
quelle

Antworten:

87

Was Sie tun können, ist, die Standard "Extras" auf dem zu entfernen input:

input.wide {display:block; width:100%;padding:0;border-width:0}

Dadurch bleibt das inputInnere des Behälters erhalten. Nun , wenn Sie die Grenzen wollen, wickeln die inputin ein div, mit den Grenzen gesetzt auf die div(auf diese Weise Sie das entfernen display:blockvon dem inputauch). Etwas wie:

<div style="border:1px solid gray;">
 <input type="text" class="wide" />
</div>

Bearbeiten: Eine andere Option besteht darin, anstatt den Stil aus dem zu entfernen input, ihn im Wraps zu kompensieren div:

input.wide {width:100%;}

<div style="padding-right:4px;padding-left:1px;margin-right:2px">
  <input type="text" class="wide" />
</div>

Dies führt in verschiedenen Browsern zu etwas unterschiedlichen Ergebnissen, die den Container jedoch nicht überlappen. Die Werte in div hängen davon ab, wie groß der Rand am Rand ist inputund wie viel Platz Sie zwischen dem inputund dem Rand benötigen.

Hilbrand Bouwkamp
quelle
3
Dies ist eine sehr kreative Lösung. Das einzige Problem, das ich damit habe, ist, dass ich keine Gliederung im Textfeld definieren kann, wenn es den Fokus erhält, es sei denn, ich verwende JavaScript, um den Rand des Wrapper-Div zu ändern.
Dan Herbert
@ DanHerbert, Sie haben Recht, das ist ein großer UX-Fehler dieser Methode
Baumr
274

Gibt es eine Möglichkeit, ein Textfeld dazu zu bringen, die Breite seines Containers zu füllen, ohne darüber hinaus zu expandieren?

Ja: Mit der CSS3-Eigenschaft 'box-sizing: border-box' können Sie neu definieren, was 'width' bedeutet, um den externen Abstand und den Rand einzuschließen.

Da es sich um CSS3 handelt, ist die Unterstützung leider nicht sehr ausgereift. Da der Spezifikationsprozess noch nicht abgeschlossen ist, hat er in der Zwischenzeit unterschiedliche temporäre Namen in Browsern. So:

input.wide {
    width: 100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
}

Die Alternative der alten Schule besteht einfach darin, eine Menge von 'padding-right' auf das umschließende <div> - oder <td> -Element zu setzen, die ungefähr der Menge an zusätzlichem links-rechts-Polster / Rand in 'px' entspricht, von der Sie glauben, dass Browser dies tun werden Geben Sie die Eingabe. (Normalerweise 6px für IE <8.)

Bobince
quelle
Dies würde großartig funktionieren, außer dass ich dies nicht verwenden kann, da ich auf mobile Geräte abziele, die dies wahrscheinlich jahrelang nicht unterstützen werden. : - \
Dan Herbert
20
Ich denke, dass mobile Geräte vor Computern volle HTML5-Unterstützung haben werden.
Mariano Cavallo
4
@Kindred: definitiv nicht, wenn Sie IEMobile und Blackberry einbeziehen.
Bobince
1
Dies hat jedoch eine großartige Unterstützung für Desktop-Browser: quirksmode.org/css/contents.html
Logan
2
Wie habe ich so lange gebraucht, um diese tolle Buttersauce zu finden ??? Können wir dies bitte zur akzeptierten Antwort machen?
Streetlogics
14

Dies löste das Problem für mich!

Ohne die Notwendigkeit eines externen Div. Wenden Sie es einfach auf Ihr angegebenes Textfeld an.

box-sizing: border-box; 

Mit dieser Eigenschaft "Die Eigenschaften width und height (und min / max) umfassen Inhalt, Abstand und Rand, jedoch nicht den Rand"

Siehe Beschreibung der Immobilie bei w3schools .

Hoffe das hilft jemandem!

Jack Trowbridge
quelle
Wunderbar einfach! Vielen Dank!
Nurider
10

Ich bin gerade selbst auf dieses Problem gestoßen, und die einzige Lösung, die in allen meinen Testbrowsern (IE6, IE7, Firefox) funktioniert hat, war die folgende:

  1. Wickeln Sie das Eingabefeld in zwei separate DIVs ein
  2. Stellen Sie den äußeren DIV auf 100% Breite ein, damit unser Container nicht über das Dokument läuft
  3. Setzen Sie eine Polsterung in den inneren DIV ein, um den horizontalen Überlauf des Eingangs auszugleichen.
  4. Stellen Sie die benutzerdefinierte Auffüllung des Eingangs so ein, dass sie um den gleichen Betrag überläuft, den ich im inneren DIV zugelassen habe

Der Code:

<div style="width: 100%">
    <div style="padding-right: 6px;">
        <input type="text" style="width: 100%; padding: 2px; margin: 0;
                                  border : solid 1px #999" />
    </div>
</div>

Hier beträgt der gesamte horizontale Überlauf für das Eingabeelement 6px - 2x (Auffüllen + Rand) - daher setzen wir ein Auffüllrecht für den inneren DIV von 6px.

Tobias Cohen
quelle
Fügen Sie dem Eingabeelement eine 8px-Polsterung hinzu und es funktioniert nicht mehr
JuHwon
7

Die Unterstützung für Box-Sizing ist eigentlich ziemlich gut: http://caniuse.com/#search=box-sizing

Wenn Sie also nicht auf IE7 abzielen, sollten Sie in der Lage sein, diese Art von Problemen mithilfe dieser Eigenschaft zu lösen. Eine Ebene wie sass oder weniger erleichtert übrigens den Umgang mit solchen Präfixregeln.

Chikamichi
quelle
3

Dies liegt daran, dass CSS 100% relativ zur gesamten Breite des Containers definiert, einschließlich seiner Ränder, Ränder und Auffüllungen. das bedeutet, dass der Platz zur Verfügung steht. zu seinem Inhalt ist eine Menge kleiner als 100%, es sei denn, der Behälter hat keine Ränder, Ränder oder Polsterung.

Dies ist kontraintuitiv und wird von vielen als Fehler angesehen, an dem wir jetzt festhalten . Dies bedeutet effektiv, dass% -Dimensionen für nichts anderes als einen Container der obersten Ebene gut sind, und selbst dann nur, wenn er keine Ränder, Ränder oder Auffüllungen aufweist.

Beachten Sie, dass die Ränder, Ränder und Auffüllungen des Textfelds gleich sind in der CSS - Größe für sie angegeben enthalten - es sind die Behälter die Dinge abwerfen.

Ich habe es mit 98% erträglich umgangen, aber das ist eine weniger als perfekte Lösung, da die Eingabefelder dazu neigen, mit zunehmender Größe des Containers weiter zu kurz zu kommen.


EDIT: Ich bin auf diese ähnliche Frage gestoßen - ich habe die gegebene Antwort nie ausprobiert und weiß nicht genau, ob sie auf Ihr Problem zutrifft, aber es scheint so.

Lawrence Dol
quelle
1

Eine Lösung, die funktionieren kann (es funktioniert für mich), besteht darin, bei der Eingabe einen negativen Rand anzuwenden (Textfeld). ... oder eine feste Breite für IE7 anzuwenden oder die Unterstützung für IE7 zu löschen. Dies führt zu einer pixelgenauen Breite. Für mich ist es 7, also habe ich 3 und 4 hinzugefügt, aber es ist immer noch pixelgenau.

Ich hatte das gleiche Problem und ich hasste es, zusätzliche Divs für die Grenze usw. zu haben!

Also hier ist meine Lösung, die zu funktionieren scheint!

Sie sollten ein Stylesheet nur für ie7 verwenden, um die Starhacks zu vermeiden.

input.text{
    background-color: #fbfbfb;
    border : solid #eee 1px;
    width: 100%;
    -box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    height: 32px;

    *line-height:32px;
    *margin-left:-3px;
    *margin-right:-4px;
    display: inline;   
    padding: 0px 0 0 5px;

}
GorillaApe
quelle
1

Wenn Sie es nicht verwenden können, können box-sizing:border-boxSie versuchen, das zu entfernen width:100%und ein sehr großes sizeAttribut in das <input>Element einzufügen. Der Nachteil ist jedoch, dass Sie das HTML ändern müssen und dies nicht nur mit CSS tun können:

<input size="1000"></input>
Siddhadev
quelle
0

Wenn Sie dies nicht dynamisch tun müssen (z. B. hat Ihr Formular eine feste Breite), können Sie die Breite der untergeordneten <input>Elemente einfach auf die Breite ihres Containers abzüglich Dekorationen wie Polsterung, Rand, Rand usw.: Einstellen .

 // the parent div here has a width of 200px:
.form-signin input[type="text"], .form-signin input[type="password"], .form-signin input[type="email"], .form-signin input[type="number"] {
  font-size: 16px;
  height: auto;
  display: block;
  width: 280px;
  margin-bottom: 15px;
  padding: 7px 9px;
}
Avishai
quelle
0

Wenn Sie die Boxgröße nicht verwenden können (z. B. wenn Sie HTML mit iText in PDF konvertieren). Versuche dies:

CSS

.input-wrapper { border: 1px solid #ccc; padding: 0 5px; min-height: 20px; } 
.input-wrapper input[type=text] { border: none; height: 20px; width: 100%; padding: 0; margin: 0; }

HTML

<div class="input-wrapper">
     <input type="text" value="" name="city"/>
</div>
Robertad
quelle
0

Das funktioniert:

<div>
    <input type="text" 
        style="margin: 5px; padding: 4px; border: 1px solid; 
        width: 200px; width: calc(100% - 20px);">
</div>

Die erste 'Breite' ist eine Fallback-Regel für ältere Browser.

Mo'in Creemers
quelle
0

Gestalten Sie die Eingabe einfach so, dass sie für die zusätzliche Auffüllung versetzt wird. Im folgenden Beispiel beträgt die Auffüllung am Eingang links und rechts 10 Pixel für einen Gesamtauffüllversatz von 20 Pixel:

input[type=text]{
   width: calc(100% - 20px);
}
Quinlo
quelle