He codificado un script (con la ayuda de un usuario aquí) que me permite expandir un div seleccionado y hacer que los otros div se comporten en consecuencia al estirarlo por igual para adaptarse al espacio restante (excepto el primero cuyo ancho es fijo).
Y aquí hay una imagen de lo que quiero lograr:
Para eso uso flex y transiciones.
Funciona bien, pero el script jQuery especifica un valor de estiramiento de "400%" (que es excelente para probar).
Ahora me gustaría que el div seleccionado se expanda / reduzca para ajustarse exactamente al contenido en lugar del valor fijo "400%".
No tengo idea de cómo podría hacer eso.
Es posible ?
Traté de clonar el div, ajustarlo al contenido, obtener su valor y luego usar este valor para la transición PERO esto significa que tengo un ancho inicial en porcentajes pero un valor objetivo en píxeles. Eso no funciona
Y si convierto el valor del píxel en porcentajes, entonces el resultado no se ajusta exactamente al contenido por el motivo que sea.
En todos los casos, esto parece una forma un poco complicada de lograr lo que quiero de todos modos.
¿No hay alguna propiedad flexible que se pueda cambiar para ajustarse al contenido de un div seleccionado?
Aquí está el código ( editado / simplificado para una mejor lectura ):
var expanded = '';
$(document).on("click", ".div:not(:first-child)", function(e) {
var thisInd =$(this).index();
if(expanded != thisInd) {
//fit clicked fluid div to its content and reset the other fluid divs
$(this).css("width", "400%");
$('.div').not(':first').not(this).css("width", "100%");
expanded = thisInd;
} else {
//reset all fluid divs
$('.div').not(':first').css("width", "100%");
expanded = '';
}
});
.wrapper {
overflow: hidden;
width: 100%;
margin-top: 20px;
border: 1px solid black;
display: flex;
justify-content: flex-start;
}
.div {
overflow: hidden;
white-space: nowrap;
border-right: 1px solid black;
text-align:center;
}
.div:first-child {
min-width: 36px;
background: #999;
}
.div:not(:first-child) {
width: 100%;
transition: width 1s;
}
.div:not(:first-child) span {
background: #ddd;
}
.div:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click on the div you want to fit/reset (except the first div)
<div class="wrapper">
<div class="div"><span>Fixed</span></div>
<div class="div"><span>Fluid (long long long long long text)</span></div>
<div class="div"><span>Fluid</span></div>
<div class="div"><span>Fluid</span></div>
</div>
Aquí está el jsfiddle:
https://jsfiddle.net/zajsLrxp/1/
EDITAR: Aquí está mi solución de trabajo con la ayuda de todos ustedes (tamaños actualizados en el cambio de tamaño de la ventana + número de divs y el ancho de la primera columna calculado dinámicamente):
var tableWidth;
var expanded = '';
var fixedDivWidth = 0;
var flexPercentage = 100/($('.column').length-1);
$(document).ready(function() {
// Set width of first fixed column
$('.column:first-child .cell .fit').each(function() {
var tempFixedDivWidth = $(this)[0].getBoundingClientRect().width;
if( tempFixedDivWidth > fixedDivWidth ){fixedDivWidth = tempFixedDivWidth;}
});
$('.column:first-child' ).css('min-width',fixedDivWidth+'px')
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
})
$(window).resize( function() {
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
})
$(document).on("click", ".column:not(:first-child)", function(e) {
var thisInd =$(this).index();
// if first click on a fluid column
if(expanded != thisInd)
{
var fitDivWidth=0;
// Set width of selected fluid column
$(this).find('.fit').each(function() {
var c = $(this)[0].getBoundingClientRect().width;
if( c > fitDivWidth ){fitDivWidth = c;}
});
tableWidth = $('.mainTable')[0].getBoundingClientRect().width;
$(this).css('flex','0 0 '+ 100/(tableWidth/fitDivWidth) +'%')
// Use remaining space equally for all other fluid column
$('.column').not(':first').not(this).css('flex','1 1 '+flexPercentage+'%')
expanded = thisInd;
}
// if second click on a fluid column
else
{
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
}
});
body{
font-family: 'Arial';
font-size: 12px;
padding: 20px;
}
.mainTable {
overflow: hidden;
width: 100%;
border: 1px solid black;
display: flex;
margin-top : 20px;
}
.cell{
height: 32px;
border-top: 1px solid black;
white-space: nowrap;
}
.cell:first-child{
background: #ccc;
border-top: none;
}
.column {
border-right: 1px solid black;
transition: flex 0.4s;
overflow: hidden;
line-height: 32px;
text-align: center;
}
.column:first-child {
background: #ccc;
}
.column:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="text">Click on the header div you want to fit/reset (except the first one which is fixed)</span>
<div class="mainTable">
<div class="column">
<div class="cell"><span class="fit">Propriété</span></div>
<div class="cell"><span class="fit">Artisan 45</span></div>
<div class="cell"><span class="fit">Waterloo 528</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Adresse</span></div>
<div class="cell"><span class="fit">Rue du puit n° 45 (E2)</span></div>
<div class="cell"><span class="fit">Chaussée de Waterloo n° 528 (E1)</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Commune</span></div>
<div class="cell"><span class="fit">Ixelles</span></div>
<div class="cell"><span class="fit">Watermael-Boitsfort</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Ville</span></div>
<div class="cell"><span class="fit">Marche-en-Famenne</span></div>
<div class="cell"><span class="fit">Bruxelles</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Surface</span></div>
<div class="cell"><span class="fit">120 m<sup>2</sup></span></div>
<div class="cell"><span class="fit">350 m<sup>2</sup></span></div>
</div>
</div>
Y aquí hay un ejemplo completo en el trabajo (estilos + relleno + más datos):
https://jsfiddle.net/zrqLowx0/2/
Gracias a todos !
fuente
Respuestas:
Es posible resolverlo usando
max-width
ycalc()
.Primero, reemplace
width: 100%
conflex: 1
los divs en CSS, para que crezcan, lo que es mejor en este caso. Además, use la transición paramax-width
.Ahora, tenemos que almacenar algunos valores relevantes:
divsLength
variable) - 3 en este caso.extraSpace
variable) - 39px en este caso.Con esas 2 variables, podemos establecer un valor predeterminado
max-width
(defaultMaxWidth
variable) para todos los divs, así como usarlos más adelante. Es por eso que se almacenan a nivel mundial.El
defaultMaxWidth
escalc((100% - extraSpace)/divsLength)
.Ahora, ingresemos la función de clic:
Para expandir el div, el ancho del texto de destino se almacenará en una variable llamada
textWidth
y se aplicará al div como lomax-width.
usa.getBoundingClientRect().width
(ya que devuelve el valor de coma flotante).Para los divs restantes, se crea un
calc()
paramax-width
que se les aplicará.Que es:
calc(100% - textWidth - extraScape)/(divsLength - 1)
.El resultado calculado es el ancho que debe tener cada div restante.
Al hacer clic en el div expandido, es decir, para volver a la normalidad, el valor predeterminado
max-width
se aplica nuevamente a todos los.div
elementos.Este enfoque se comporta dinámicamente y debería funcionar en cualquier resolución.
El único valor que necesita para codificar es la
extraSpace
variable.fuente
Debes ocuparte de las funciones ancho o calc. Flexbox tendría una solución.
Para hacer todos los divs iguales (no el primero) usamos
flex: 1 1 auto
.Defina reglas flexibles para su div normal y div seleccionado.
transition: flex 1s;
es tu amigo. Para el seleccionado no necesitamos crecimiento flexible, así que usamosflex: 0 0 auto
;Agregue la clase seleccionada cada vez que el usuario haga clic en un div. También puede usar alternar para el segundo clic para poder guardar los elementos seleccionados en un mapa y puede mostrar varios elementos seleccionados (no con este ejemplo de código, por supuesto).
https://jsfiddle.net/f3ao8xcj/
fuente
Flex transition: Stretch (or shrink) to fit content
es el título de su pregunta y esta respuesta es el simple ejemplo de cómo hacerlo. Es su responsabilidad encontrar la solución para su caso.Después de algunas versiones de prueba, esta parece ser mi solución más corta y directa.
Todo lo que hay en esencia hay que hacer es estirar Flexbox tienen los
<div>
elementos a sus límites por defecto, pero cuando<span>
se hace clic, la restricción del tramo de la<div>
de<span>
ancho ...pseudocódigo:
when <span> clicked and already toggled then <div> max-width = 100%, reset <span> toggle state
otherwise <div> max-width = <span> width, set <span> toggle state
He dividido el CSS en una sección de 'mecanismo relevante' y 'solo para los ojos' para facilitar la lectura (y el reciclaje del código).
El código está muy comentado, así que no hay mucho texto aquí ...
Quirk De alguna manera hay un retraso adicional en el
transition
cuando se cambiadiv
demax-width: 100%
amax-width = span width
. He comprobado este comportamiento en Chrome, Edge, IE11 y Firefox (todos W10) y todos parecen tener esta peculiaridad. O se está produciendo algún recálculo interno del navegador, o tal vez eltransition
tiempo se usa dos veces ('parece') Viceversa, por extraño que parezca, no hay retraso adicional.Sin embargo, con un tiempo de transición corto (p. Ej., 150 ms, como lo estoy usando ahora), este retraso adicional no es / apenas se nota. (Agradable para otra pregunta SO ...)
Mostrar fragmento de código
ACTUALIZAR
Nueva versión que restablece todas las demás
<div>
. Realmente odio el nerviosismo, pero eso se debe al estiramiento de Flexbox y altransition
valor. Sintransition
saltos visibles. Necesita probar lo que funciona para usted.Solo agregué
document.querySelectorAll()
el código javascript.Mostrar fragmento de código
fuente