div - title html5
Columnas de fluido CSS, márgenes fijos; el santo grial de los santos griales (10)
Actualización y resumen
Me siento obligado a aclarar esta cuestión, ahora que hay una recompensa adjunta.
( Además, estoy bastante seguro de que esto será un juego de niños cuando se admite el valor de la unidad width: calc(25% - 5px)
, haciendo algo así como width: calc(25% - 5px)
; aunque probablemente width: calc(25% - 5px)
por Internet en nuestras mentes ese punto )
Estoy trabajando en un marco CSS para algunos proyectos que comparten requisitos de diseño; es decir, un diseño fluido de 12 columnas. El uso de elementos flotantes de .column
con anchuras porcentuales de (100% / 12) x col_size
, esto es razonablemente fácil. Sin embargo, el problema viene con la adición de márgenes fijos ( o cualquier forma de espaciado ) entre columnas.
Mi intento inicial usó las columnas de fluido como se describe, con un hijo de .panel
anidado en cada una. Fragmento de HTML / CSS a continuación ( reducido para abreviar ):
.column{
float: left;
display: inline-block;
}
.width-01{ width: 8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width: 25%; }
/* etc */
.panel{
width: 100%;
padding: 5px;
box-sizing: border-box; /* so padding doesn''t increase width */
}
<div class="column width-02">
<div class="panel">Width-02</div>
</div>
<div class="column width-03">
<div class="panel">Width-03</div>
</div>
<div class="column width-02">
<div class="panel">Width-02</div>
</div>
<div class="column width-05">
<div class="panel">Width-05</div>
</div>
Este fragmento produciría un diseño similar al de la imagen siguiente, sin embargo, todos los elementos del 5px
tienen 5px
relleno de 5 5px
en todos los lados. Estoy tratando de hacer que el borde del contenido de las columnas exteriores se nivele con el borde del puerto de visualización ( o contenedor principal para el caso ) . Otro enfoque sería eliminar la clase .panel
completo, y solo ir con columnas:
.column{
float: left;
display: inline-block;
padding-left: 10px;
box-sizing: border-box;
}
.column:first-child{ padding-left: 0px; }
.width-01{ width: 8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width: 25%; }
/* etc */
<div class="column width-02">Width-02</div>
<div class="column width-03">Width-03</div>
<div class="column width-02">Width-02</div>
<div class="column width-05">Width-05</div>
Nuevamente, esto funciona bien, produciendo resultados aún más cercanos a los de la imagen siguiente, sin embargo, ahora el problema ( real ) es que el relleno se está comiendo en el ancho de las columnas atornillando la distribución del ancho. La columna :first-child
tiene 10 píxeles ( o el tamaño del margen ) mayor ancho del área de contenido que sus hermanos.
Esto puede parecer inocuo, incluso imperceptible; sin embargo, hay algunos casos en los que es necesario tener una distribución de ancho exacta (lo más exacta posible ) entre los elementos, o sería mucho más fácil.
Y así, ya sea que use relleno, margen o alguna combinación de los mismos; ¿Hay alguna solución para las columnas de fluido, los márgenes fijos, con una distribución uniforme del espacio de la canaleta que no robe el área de contenido "marginal" (*** haha * ) de las columnas adyacentes? **
Pregunta original
Debido a la simple falta de resultados en mis búsquedas e intentos, he llegado a la conclusión de que esto es imposible. Si en cualquier lugar puede dar una respuesta, estoy seguro de que está aquí.
¿Hay alguna manera, utilizando CSS puro, para lograr un diseño de columna de ancho de fluido con márgenes de ancho fijo?
Nota importante : esta figura es solo un ejemplo, y no el diseño específico que estoy buscando lograr. Una solución dada debería permitir cualquier combinación de columnas adyacentes, la distribución de ancho total totaliza 12 o menos. Considere la popular grilla 960 como referencia).
Nota : En un diseño de 12 columnas, la distribución de ancho de las columnas en la imagen es 2, 3, 2 y 5, respectivamente.
Hasta ahora, he recurrido a una grilla que, usando porcentajes, casi logra esto. El problema es que, para lograr los márgenes, cada columna requiere un hijo adicional (los llamo .panel
) con:
width: 100%;
box-sizing: border-box;
padding: 10px;
Esto es, de nuevo casi , bien; el problema es que con este enfoque es que la primera y la última columna tienen "márgenes" 10px
( 10px
) y los "márgenes" entre cada columna se duplican ( 2 x 10px
)
Ciertamente, con la inclusión del nuevo tipo de valor CSS3 calc()
, esto podría resolverse mucho más fácilmente. Algo en la dirección de:
.width-12 > .panel{ width: 100%; }
.width-09 > .panel{
width: calc(75% - 10px);
margin: ...;
}
Tengo algunas correcciones de JavaScript, he pirateado algunas cosas que "funcionan", pero estoy en una búsqueda. Con suerte, el más santo de los griales existe.
La siguiente solución, y la que proporcionó @avall (aunque ciertamente es una buena opción para simplificar) lamentablemente no son lo que estoy buscando. El principal problema es que los márgenes no se distribuyen de manera uniforme entre las columnas.
La única forma en que puedo ver que esto funciona es reducir el relleno de 5px
a 5px
y algo así como:
.column:first-child > .panel {
padding-left: 0px;
}
.column:last-child > .panel {
padding-right: 0px;
}
/* not necessary? in any case, haven''t tested */
.column:only-child > .panel {
padding-right: 0px;
padding-left: 0px;
}
Esta solución no es aceptable, solo porque IE8 no reconoce los pseudo selectores de :last-child
( y para el caso, :only-child
).
¿Por qué no usar el relleno como en su primer ejemplo y luego establecer el tamaño de la caja: border-box en todos los elementos?
En referencia a la pregunta original "¿Hay alguna manera, utilizando CSS puro, para lograr un diseño de columna de ancho de fluido con márgenes de ancho fijo?"
Es notable cuán extremadamente difícil es CSS con este tipo de preguntas. La semana pasada he estado trabajando en una ''plantilla base'' para crear mi propio ''Santo Grial'', que incluye borde, margen y rellenos ... Parece que CSS falla para este tipo de preguntas. Aunque la pregunta en mente es bastante fácil, se vuelve (¿casi?) Imposible de lograr en CSS, especialmente en el navegador cruzado.
La parte divertida es que estas preguntas se resuelven fácilmente mediante el uso de tablas. No entiendo por qué la sociedad web nos está forzando a usar div en lugar de argumentos tan vagos como ''semántica'' y ''fácil descripción'' ya que la mayoría de los argumentos son débiles o incluso falsos. Las personas que dicen que las tablas están dando más problemas, claramente no comprenden la verdadera dificultad que se encuentra dentro de CSS.
De todos modos, si quieres tener una estructura de tabla (ya que las columnas son parte de una tabla) sugiero usar ''display: table''.
Para lograr la imagen debajo de la pregunta original con CSS puro, se puede usar lo siguiente:
CSS
html,body{
margin: 0px;
padding: 0px;
height: 100%;
width: 100%;
overflow: auto;
}
.table{
background: pink;
display: table;
width: 100%;
height: 100%;
}
.tableRow{
display: table-row;
}
.tableCell{
display: table-cell;
vertical-align: top;
height: 100%;
}
/*
Ensures the full size of the table-cell has the behaviour of a block-element.
This is needed, because ''table-cell'' will behave differently in different browsers.
*/
.tableCell>div{
height: 100%;
}
/*
Padding has to be used instead of margin in ''border-box'' modus.
*/
.tableCell>div>div{
height: 100%;
box-sizing:border-box;
-moz-box-sizing:border-box;
}
/*
The final content.
*/
.tableCell>div>div>div{
background: lightblue;
padding: 5px;
height: 100%;
box-sizing:border-box;
-moz-box-sizing:border-box;
}
#col1{
width: 16.66%;
}
#col1>div>div{
padding-right: 10px;
}
#col2{
width: 25%;
}
#col2>div>div{
padding-right: 10px;
}
#col3{
width: 16.66%;
}
#col3>div>div{
padding-right: 10px;
}
#col4{
width: 41.66%;
}
HTML
<div class="table">
<div class="tableRow">
<div id=''col1'' class="tableCell">
<div><div><div>16.66%</div></div></div>
</div>
<div id=''col2'' class="tableCell">
<div><div><div>25%</div></div></div>
</div>
<div id=''col3'' class="tableCell">
<div><div><div>16.66%</div></div></div>
</div>
<div id=''col4'' class="tableCell">
<div><div><div>41.66%</div></div></div>
</div>
</div>
</div>
Diría que es bastante exagerado usar divisiones adicionales por solo un margen, pero desafortunadamente CSS no tiene un modelo de ''caja de margen'', que realmente resolvería mil millones de problemas.
Esta cantidad de código anidado podría hacerte pensar ''¿por qué no usar otras técnicas?'' ya que eso puede dar como resultado menos código. Para un deseo muy específico ese sería el caso. Sin embargo, otras técnicas a menudo implican un posicionamiento flotante o absoluto. Estas técnicas no pueden lograr lo mismo: los flotadores, por ejemplo, pueden lograr columnas de igual longitud, pero cuando quieres un borde o margen te encontrarás en problemas. Para el posicionamiento absoluto, es más bien lo contrario: puede resolver el problema de margen, pero la altura solo puede basarse en una columna.
En mi opinión, CSS no ha cumplido con los requisitos. Si bien es necesario reemplazar las tablas para posicionar, después de todos estos años aún no es posible obtener los mismos resultados. Para lograr ''el santo grial de los santos griales'' las estructuras de las mesas no son solo la forma más fácil, también existe la única manera ... al menos, hasta donde sé, después de probar cientos de posibilidades.
La pregunta restante es: ¿por qué usar los divs si los está usando como tablas? Esto no me entiendo completamente, pero la gente parece tener sus razones para eso.
Mira la respuesta de thirtydot en este hilo de un puro CSS / HTML (diseño fluido con "columnas" igualmente espaciadas sin JavaScript) ...
Ancho del fluido con DIV igualmente espaciados
http://jsfiddle.net/thirtydot/EDp8R/
La modificación de JSFiddle demuestra que las "columnas" pueden tener diferentes anchos fijos y aún tener márgenes iguales y fluidos.
Luego, finalmente, otro ejemplo que usa porcentajes mientras mantiene márgenes iguales y fluidos.
Me doy cuenta de que esta puede no ser una solución exacta, pero te hace sentir muy cerca, creo.
Por qué no usas
.column > .panel {
padding: 10px 0 10px 10px;
}
.column:first-child > .panel {
padding-left: 0px;
}
Hará espacios de 10px solo entre cajas y sin usar last-child.
Prueba esta solución pura de CSS2: demo fiddle
Base CSS ( fiddle sin los cosméticos) :
html, body {
padding: 0;
margin: 0;
}
#wrap {
padding-right: 30px;
overflow: hidden;
}
.col {
float: left;
margin-left: 40px;
margin-right: -30px;
}
.col:first-child {
margin-left: 0;
}
.small {
width: 16.66%;
}
.medium {
width: 25%;
}
.large {
width: 41.66%;
}
HTML:
<div id="wrap">
<div class="col small"></div>
<div class="col medium"></div>
<div class="col small"></div>
<div class="col large"></div>
</div>
Probado en Win7 en IE7, IE8, IE9, Opera 11.50, Safari 5.0.5, FF 6.0, Chrome 13.0.
Actualizar:
Ahora, si desea que esto funcione con un número arbitrario de columnas, debe agregar una clase adicional al contenedor que especifica el recuento de columnas:
<div class="cols-12 count-04">
<div class="col width-02"></div>
<div class="col width-03"></div>
<div class="col width-02"></div>
<div class="col width-05"></div>
</div>
Vea este violín actualizado que demuestra varios recuentos de columnas diferentes.
Posible error:
Teóricamente, esta solución debería funcionar para cualquier cantidad de columnas por cada ancho de columna mínimo posible en cualquier ancho de ventana del navegador. Pero parece que todos los navegadores demuestran no ser capaces de manejar: 1. un gran número de columnas de ancho de 1 columna, o 2. un ancho de ventana de navegador pequeño.
Tenga en cuenta que todos los navegadores con un ancho mínimo de 1440 píxeles, que equivale a 12 veces 120 píxeles (el espacio ocupado por todos los márgenes de 10px), manejan la solución perfectamente. Y cuando utiliza 2 o más columnas de ancho de columna, el requisito para el ancho mínimo del navegador de hecho cae a 720 píxeles (6 * 120px). Este último caso parece más realista, pero aun así, no puedo explicar el comportamiento de este navegador.
Traté de solucionar el problema mediante la introducción de una última clase de columna adicional como lo demuestra este violín , pero no resuelve el problema para los anchos de navegador pequeños. Sin embargo, resuelve un pequeño error de redondeo debido a los porcentajes de ancho rotos, pero supongo que ese problema podría ignorarse.
Me gustaría saber de otros expertos de CSS sobre este, así que agregué una recompensa.
Recientemente he desarrollado una solución alternativa para esto que permite cualquier combinación de columnas flexibles dentro de una fila con un margen fijo y constante en todas las columnas, independientemente del ancho del elemento padre.
Esto no usa ningún JavaScript y funciona en IE8 +.
En esta solución, el margen se define en dos clases, por lo que es fácil cambiarlo para diseños receptivos. Los anchos de columna también son representativos del espacio que utilizan, por ejemplo, una fila de 2 columnas tiene un ancho del 50% y una fila de 4 columnas tiene un ancho del 25%.
Puede ver un ejemplo en http://www.andrewjamestait.co.uk/conflexgrids/
O está disponible en GitHub en https://github.com/andrewjtait/conflexgrids
Si puede vivir con otro div anidado por columna, puede definir el margen deseado para cada uno. Para deshacerse del margen en los bordes exteriores izquierdo y derecho, puede definir un margen negativo en el contenedor externo.
Ejemplo: Usar pureCSS pure-g es el contenedor externo, pure-u- * es un nodo de columna (display: inline-block) que contiene el div anidado. spacing es el nombre de esta extensión personalizada del sistema de grillas pureCSS para permitir márgenes de columna.
.pure-g.spacing {
margin: 0 -10px;
}
.pure-g.spacing [class *= "pure-u"] > div {
margin: 10px;
}
Debería funcionar en la mayoría de los navegadores. Dime si no, ya lo estoy usando.
saludos, Max
Una manera más fácil de obtener el mismo efecto es permitir que el contenido dentro de sus columnas cree sus canaletas en lugar de aplicar márgenes / relleno a las columnas mismas. Esto se puede hacer con rejillas fijas, fluidas, elásticas, etc.
Por ejemplo:
/* Gutters */
h1, h2, h3, h4, h5, h6,
p, ul, ol, blockquote,
hr, address, pre, object, fieldset
{
margin-right: .75rem;
margin-left: .75rem;
padding-right: .75rem;
padding-left: .75rem;
}
Esto también simplifica el tamaño de sus columnas, anidamiento y aplicación de fondos a sus piezas de lego.
Yo uso la grilla de OOCSS para esto
https://github.com/stubbornella/oocss
Recientemente puse una demostración en línea en mi propio sitio ya que no hay ejemplos adecuados en línea :(
http://www.leipeshit.com/awesome_stuff/oocss/core/grid/grids_all.html
Finalmente lo descubrí. Después de cientos de horas perdidas en la última década (aunque estoy confiando en algún CSS que de todos modos no hubiera funcionado). Lo resolví sin ningún problema. y en IE8 +.
Por favor, preparen el 2001: A Space Odyssey Music porque estoy aterrizando este bote.
El genio y el truco de este método es usar elementos de bloque en línea y luego usar espaciado de palabras para contrabalancear utilizando un margen derecho negativo. Un margen derecho negativo por sí mismo juntará los elementos, lo que le permite tener un ancho del 100% establecido y aún ajustar las cosas intermedias, pero deja los elementos superpuestos. Al establecer un margen negativo en el elemento primario solo se deshace el margen secundario en lo que respecta al efecto de interactuar con el ancho total (la marca mágica "100% de ancho" que estamos intentando alcanzar "). El relleno solo sirve para aumentar el tamaño del elemento. y es inútil con respecto al margen de contraataque. A menudo se utiliza con el tamaño de caja en las soluciones arregladas para este problema, a expensas de perder la capacidad de usar relleno de lo contrario (y margen) y probablemente requiera más elementos de envoltura.
el espaciado de palabras proporciona la "tercera vía" mágica para agregar o eliminar la distancia horizontal entre dos elementos, siempre que sean bloques en línea, ya que se contarán como una sola "palabra" en ese caso, y cualquier espacio en blanco entre ellos se reducirá a la única propiedad de "espaciado de palabras" controlable. Aparte de este truco, no conozco otra forma de obtener este resultado al 100%.
Presento humildemente la respuesta definitiva al problema de las columnas flexibles de canales fijos. Por este medio nombre mi solución "la maniobra omega". Viene con la capacidad de manejar columnas de ancho mixto arbitrarias (agregando hasta un 100% del ancho total exactamente o un poco menos para el redondeo), cualquier tamaño de canal, cualquier cantidad predefinida de columnas en ancho, maneja cantidades arbitrarias de filas con ajuste automático, y utiliza elementos de bloque en línea, por lo tanto, proporciona las opciones de alineación vertical que vienen con el bloque en línea, Y no requiere ningún marcado adicional y solo requiere una declaración de clase única en el contenedor (sin contar anchos de columna definitorios). Creo que el código habla por sí mismo. Aquí está la implementación del código para 2-6 columnas usando 10px cunetas y clases auxiliares de bonificación para porcentajes.
EDITAR: interesante acertijo. He logrado obtener dos versiones ligeramente diferentes; uno para mozilla y ie8 +, el otro para webkit. Parece que el truco de espaciado de palabras no funciona en webkit, y no sé por qué la otra versión funciona en webkit pero no es ie8 + / mozilla. La combinación de ambos te ofrece cobertura sobre todo y estoy dispuesto a apostar que hay una manera de unificar esta táctica o algo muy similar para evitar el problema.
EDIT2: ¡Casi lo tengo! Magical text-align: justify
consigue WebKit casi allí con el espaciado de palabras. El espaciado parece un poco apagado, como una cuestión de píxeles a la derecha y tal vez uno más en las cunetas. Pero es utilizable y parece más confiable para mantener las columnas que cualquier cosa que haya usado antes. Nunca reduce las columnas, se comprime hasta que el navegador obtiene una barra de desplazamiento horizontal.
Edit3: lo tengo un poco cerca de perfecto. Establecer el tamaño de fuente en 0 normaliza la mayoría de los problemas restantes con el espaciado desactivado. Solo tengo que arreglar IE9 ahora, que colapsará si la fuente es tamaño 0.
EDIT4: Obtuve la respuesta al IE desde algunas otras publicaciones de ancho de fluido: -ms-text-justify: distribute-all-lines
. Probado en IE8-10.
/* The Omega Maneuver */
[class*=cols] { text-align: justify; padding-left: 10px; font-size: 0;
-ms-text-justify: distribute-all-lines; }
[class*=cols]>* { display: inline-block; text-align: left; font-size: 13px;
word-spacing: normal; vertical-align: top;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.cols2 { word-spacing: 20px; padding-right: 20px; }
.cols3 { word-spacing: 30px; padding-right: 30px; }
.cols4 { word-spacing: 40px; padding-right: 40px; }
.cols5 { word-spacing: 50px; padding-right: 50px; }
.cols6 { word-spacing: 60px; padding-right: 60px; }
.cols2 > * { margin-right: -10px; }
.cols3 > * { margin-right: -20px; }
.cols4 > * { margin-right: -30px; }
.cols5 > * { margin-right: -40px; }
.cols6 > * { margin-right: -50px; }
Algunos ayudantes:
.⅛, .⅛s >* { width: 12.50%; }
.⅙, .⅙s >* { width: 16.66%; }
.⅕, .⅕s >* { width: 20.00%; }
.¼, .¼s >* { width: 25.00%; }
.⅓, .⅓s >* { width: 33.00%; }
.⅜, .⅜s >* { width: 37.50%; }
.⅖, .⅖s >* { width: 40.00%; }
.½, .½s >* { width: 50.00%; }
.⅗, .⅗s >* { width: 60.00%; }
.⅝, .⅝s >* { width: 62.50%; }
.⅔, .⅔s >* { width: 66.00%; }
.¾, .¾s >* { width: 75.00%; }
.⅘, .⅘s >* { width: 80.00%; }
.⅚, .⅚s >* { width: 83.33%; }
.⅞, .⅞s >* { width: 87.50%; }
.blarg-five-twelfs { width: 41.66%; }
Puedes presenciar mi obra maestra en acción entre un campo de gloria aquí: http://jsfiddle.net/xg7nB/15/
<div class="cols4">
<div class="⅙">This is my magnum opus</div>
<div class="¼">I finally beat css</div>
<div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
<div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>
La implementación mínima absoluta, usando como ejemplo 4 columnas de igual ancho (25%) de ancho y 10px cunetas, es así:
.fourEqualCols { word-spacing: 40px; padding: 0 40px 0 10px;
text-align: justify; font-size: 0;
-ms-text-justify: distribute-all-lines; }
.fourEqualCols>* { margin-right: -30px; width: 25%;
display: inline-block; word-spacing: normal;
text-align: left; font-size: 13px; }
<div class="fourEqualCols ">
<div>GLORIOUSLY CLEAN MARKUP</div>
<div>I hate extra markup and excessive class props</div>
<div>Naked code</div>
<div>get intimate</div>
</div>
Así que este código esencialmente reemplaza prácticamente a cualquier marco de grilla existente ¿no? Si puede establecer canaletas arbitrariamente y luego hacer conjuntos de columnas que alcancen el 100% de ancho, eso es estrictamente superior a la mayoría de los marcos de cuadrícula, de hecho, ¿no es así? Si ya no estás desarrollando para IE7 como muchos de nosotros, eso combinado con el tamaño de la caja: border-box hace que el relleno y el borde también no sean un problema.
Editar: oh derecho, querías estar al ras con los lados del contenedor. No hay problema con esto, tuve que agregar canalones laterales específicamente para que podamos cambiar algunos valores por 10 y deshacernos del relleno y voila. http://jsfiddle.net/bTty3/
[class^=cols] { text-align: justify; font-size: 0;
-ms-text-justify: distribute-all-lines; }
[class^=cols] >* { display: inline-block; text-align: left; font-size: 13px;
word-spacing: normal; vertical-align: top;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.cols2 { word-spacing: 20px; padding-right: 10px; }
.cols3 { word-spacing: 30px; padding-right: 20px; }
.cols4 { word-spacing: 40px; padding-right: 30px; }
.cols5 { word-spacing: 50px; padding-right: 40px; }
.cols6 { word-spacing: 60px; padding-right: 50px; }
.cols2 >* { margin-right: 0 }
.cols2 >* { margin-right: -10px; }
.cols3 >* { margin-right: -20px; }
.cols4 >* { margin-right: -30px; }
.cols5 >* { margin-right: -40px; }
.cols6 >* { margin-right: -50px; }
Mismo html
<div class="cols4">
<div class="⅙">This is my magnum opus</div>
<div class="¼">I finally beat css</div>
<div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
<div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>