Pregunta Un elemento móvil para empujar el elemento adyacente solo si colisionan


Tengo un contenedor con 2 niños.

Un niño tiene un ancho dinámico y en su ancho máximo puede llenar el contenedor

El otro niño tiene un ancho fijo y comienza a estar oculto ya que su punto de partida está a la derecha del overflow:hidden envase

Lo que quiero es que el niño de ancho fijo se mueva hacia la izquierda para que se ajuste exactamente a la derecha del contenedor de modo que

a) Si ambos niños caben en el contenedor - el otro elemento debe decir poner a la izquierda y

b) Si no hay espacio para ambos elementos, el elemento de ancho fijo debe empujar el otro elemento hacia la izquierda tanto como sea necesario para encajar en el derecho del contenedor.

Esto es lo que intenté:

Intento # 1

.container {
  width: 200px;
  height: 50px;
  border: 1px solid green;
  overflow: hidden;
  white-space: noWrap;
}
span {
  height: 50px;
  display: inline-block;
}
.child1 {
  background: aqua;
  float: right;
  width: 50px;
  margin-right: -50px;
  transition: margin .2s;
}
.container:hover .child1 {
  margin-right: 0;
}
.child2 {
  background: tomato;
  //width: 100%;  

}
<div class="container">
  <span class="child1">Fixed</span>
  <span class="child2">Dynamic Width</span>
</div>

<div class="container">
  <span class="child1">Fixed</span>
  <span class="child2">Here is a Dynamic Width box</span>
</div>

Condición a) Tiene éxito pero la condición b) Se produce un error

Intento # 2

.container {
  width: 200px;
  height: 50px;
  border: 1px solid green;
  overflow: hidden;
  white-space: noWrap;
}
span {
  height: 50px;
  display: inline-block;
}
.child2 {
  background: aqua;
  width: 50px;
  margin: 0;
  float: right;
  margin-right: -50px;
  transition: margin .2s;
}
.container:hover .child1 {
  margin-left: -50px;
}
.container:hover .child2 {
  margin: 0;
}
.child1 {
  background: tomato;
  transition: margin .2s;
}
<div class="container">
  <span class="child1">Dynamic Width</span>
  <span class="child2">Fixed</span>
</div>

<div class="container">

  <span class="child1">Here is a Dynamic Width box</span>
  <span class="child2">Fixed</span>
</div>

Condición a) Fallas y condición b) Sucede

¿Se pueden cumplir ambas condiciones solo con CSS?

PD: El marcado que proporcioné en las demostraciones puede ser modificado. También CSS3 incluyendo flexbox también está bien.


32
2018-02-10 10:46


origen


Respuestas:


Aquí hay una solución de CSS única.

El truco es usar esta regla básica:
Considere dos o más elementos en línea renderizados uno al lado del otro. Si aumenta el ancho del primer elemento, el segundo elemento se empuja hacia la derecha.

El problema es que necesitas que los elementos se muevan hacia la izquierda. Lo resolví invirtiendo la dirección X en los elementos secundarios scaleX(-1) y volver a invertir de nuevo el contenedor.

Para ayudarlo a comprender mejor esto, puede comentar el transform: scaleX(-1); en el enlace jsfiddle a continuación, y mira lo que sucede.

La belleza de esto es que no necesitas saber el ancho del .child2. Solo tienes que empujarlo hacia la izquierda.

.container {
    width: 200px;
    height: 50px;
    border: 1px solid green;
    overflow: hidden;
    white-space: nowrap;
    text-align: right;
    transform: scaleX(-1);
}

span {
   height: 50px;
   display: inline-block;
   transform: scaleX(-1);
}

.child1 {
    background: aqua;
    width: 50px;
    margin-left: -50px;
    float: left;
    transition: margin-left .2s;
    text-align: left;
}

.child2 {
   background: tomato;
}

.container:hover .child1 {
    margin-left: 0;
}
<div class="container">
    <span class="child1">Fixed</span>
    <span class="child2">Dynamic Width</span>
</div>

<div class="container">
    <span class="child1">Fixed</span>
    <span class="child2">Here is a Dynamic Width box</span>
</div>

También en jsfiddle


Solución 2

Otra solución un poco más simple es usar direction: rtl; en el contenedor. Al invertir la dirección de los elementos en línea de rOcho to left, logramos el mismo efecto sin la necesidad de usar transformaciones CSS3.
Ver http://jsfiddle.net/epfqjtft/12/


31
2018-02-10 12:24



Como css no puede hacer declaraciones condicionales (barras de consultas de medios), no creo que esto sea verdaderamente posible con css solo.

actualizar


Lo he visto es de hecho es posible usar transformaciones CSS3 (que funciona en navegadores modernos). pero solo en caso de que algunos usuarios quieran soporte de navegador más antiguo que las transformaciones CSS3 no pueden proporcionar, lo dejaré aquí de todos modos.


Aparte de eso, he usado posicionamiento en lugar de flotadores para 'limpiar' el estilo (e intenté el jquery):

$('.container').hover(function() {

  var parentWidth = $(this).width();
  var thisWidth = $(this).find(".child1").width() + 50; /*i.e. width of fixed box*/
  if (parentWidth < thisWidth) { /*if it doesn't fit, move it!*/
    $(this).find('.child1').addClass("moveLeft");
  }
}, function() {
  $(this).find(".child1").removeClass("moveLeft");
});
.container {
  width: 200px;
  height: 50px;
  border: 1px solid green;
  overflow: hidden;
  white-space: noWrap;
  position: relative;
}
span {
  height: 50px;
  display: inline-block;
}
.child2 {
  background: aqua;
  width: 50px;
  margin: 0;
  position: absolute;
  top: 0;
  right: -50px;
  transition: all .2s;
}
.child1 {
  background: tomato;
  transition: all .2s;
  position: absolute;
  top: 0;
  left: 0;
}
.container:hover .child2 {
  right: 0;
}
.moveLeft:hover {
  left: -50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <span class="child1">Dynamic Width</span>
  <span class="child2">Fixed</span>
</div>
<div class="container">
  <span class="child1">Here is a Dynamic Width box</span>
  <span class="child2">Fixed</span>
</div>


En cuanto a su 'solución', tendrá que probar si child + 50px es greater than el ancho principal, si es así, mover child1. Si no, no se necesita ninguna acción.


7
2018-02-10 11:12



De acuerdo, cambié el código de LinkinTED un poco. Prueba esto: http://jsfiddle.net/epfqjtft/9/

Por supuesto, no sé si es algo con lo que puedes trabajar. Este tipo de problemas deberían resolverse con Jquery.

.container {
    width: 200px;
    height: 50px;
    border: 1px solid green;

    display: table;
    table-layout: fixed;
    transition: all 2s;
}
span {
   height: 50px;
   display: table-cell;
    transition: all .2s;
}
.child1 {
    background: tomato;
    width: 100%;
}
.child2 {
    background: aqua;
    width: 0px;
    overflow: hidden;
    transition: all .2s;
}
.container:hover .child2 {
    width: 50px;
}

<div class="container">
    <div class="wrapper">
        <span class="child1">Dynamic Width</span>
    </div>
    <span class="child2">Fixed</span>
</div>    
<div class="container">
    <div class="wrapper">
        <span class="child1">Here is a Dynamic Width box</span>
    </div>
    <span class="child2">Fixed</span>
</div>

3
2018-02-10 11:43



.container {
    width: 250px;
    height: 40px;
    border: 1px solid read;
    overflow: hidden;
    white-space: nowrap;
    text-align: right;
    transform: scaleX(-1);
}

span {
   height: 50px;
   display: inline-block;
   transform: scaleX(-1);
}

.child1 {
    background: pink;
    width: 50px;
    margin-left: -50px;
    float: left;
    transition: margin-left .3s;
    text-align: left;
}

.child2 {
   background: #####;
}

.container:hover .child1 {
    margin-left: 0;
}
<div class="container">
    <span class="child1">Fixed</span>
    <span class="child2">Dynamic Width</span>
</div>

<div class="container">
    <span class="child1">Fixed</span>
    <span class="child2">Here is  Dynamic Width box</span>
</div>


-1
2018-04-23 09:06