html - una - ¿Cómo evitar que un elemento posicionado absolutamente afecte a la barra de desplazamiento?
scroll personalizado (9)
Considere una entrada de sugerencia automática que se encuentre en un contenedor con algo de contenido y una barra de desplazamiento vertical:
Cuando se muestran sugerencias de autosugestión, deben aparecer en la parte superior del contenido sin afectar la barra de desplazamiento del contenedor .
Espero obtener:
Tenga en cuenta que la barra de desplazamiento es exactamente la misma que la anterior.
Pero, obtengo lo siguiente:
Tenga en cuenta que la barra de desplazamiento se ve afectada y las sugerencias se cortan.
¿Por qué las sugerencias absolutamente posicionadas afectan la barra de desplazamiento del contenedor?
¿Cómo arreglarías eso?
Notas:
- Al desplazarse por el contenedor, la entrada y las sugerencias deben moverse juntas.
- Se le permite modificar el HTML, pero la entrada y la lista de sugerencias deben permanecer dentro de
.autosuggest
(considere.autosuggest
como un componente de terceros cuyo HTML no se puede cambiar, pero puede cambiar su CSS). - Puedes usar flexbox, si te ayuda.
- Estoy buscando una solución CSS única. No Javascript por favor.
.container {
height: 100px;
width: 300px;
margin-top: 50px;
overflow-y: auto;
border: 1px solid black;
}
.autosuggest {
position: relative;
width: 250px;
}
.input {
font-size: 16px;
width: 230px;
padding: 5px 10px;
border: 0;
background-color: #FFEBBF;
}
.suggestions {
list-style-type: none;
margin: 0;
padding: 5px 10px;
width: 230px;
background-color: #85DDFF;
position: absolute;
}
.content {
width: 120px;
padding: 5px 10px;
}
<div class="container">
<div class="autosuggest">
<input class="input" type="text" value="input">
</div>
<div class="content">
content content content content content content content content content content
</div>
</div>
<div class="container">
<div class="autosuggest">
<input class="input" type="text" value="input">
<ul class="suggestions">
<li>suggestion 1</li>
<li>suggestion 2</li>
<li>suggestion 3</li>
<li>suggestion 4</li>
<li>suggestion 5</li>
<li>suggestion 6</li>
<li>suggestion 7</li>
<li>suggestion 8</li>
<li>suggestion 9</li>
</ul>
</div>
<div class="content">
content content content content content content content content content content
</div>
</div>
- Cuando se muestran sugerencias de sugerencia automática, deben aparecer sobre el contenido sin afectar la barra de desplazamiento del contenedor.
- Al desplazar el contenedor, la entrada y las sugerencias deben moverse juntas.
Esto no puede hacerse solo con CSS.
Para que las suggestions
aparezcan en la parte superior del container
del container
, sin recortar, debe tener la position: absolute
y ninguno de sus elementos principales ( autosuggest
y container
) puede ser position: relative
.
El lado negativo es que las suggestions
no se moverán en scroll.
Para que las suggestions
muevan con scroll, uno de sus padres ( autosuggest
o container
) debe ser position: relative
.
El lado negativo es que, como el container
no está overflow: visible
, se recortará
Como ya se sugirió, y se supone que la input
debe estar dentro del elemento autosuggest
, cambiar la position: relative
en el autosuggest
a position: absolute
, por lo que la input
permanece con suggestions
en desplazamiento, probablemente sea la mejor, aunque establezca z-index
en Cada container
será necesario para evitar superposiciones extrañas.
Pero si el proveedor del componente de terceros , ... :) ..., pudiera ser convencido de que la input
podría ubicarse fuera del elemento de autosuggest
, se podría obtener un poco más de control, usando solo CSS, tanto del suggestions
y el content
y sus diseños, basados en si la input
tiene un enfoque o no, ...
... donde esta muestra podría ser un buen comienzo (haga clic en la input
para mostrar suggestions
).
.container {
background-color: white;
width: 300px;
min-height: 100px;
margin-top: 50px;
border: 1px solid black;
overflow: auto;
position: relative;
}
.autosuggest {
position: relative;
width: 250px;
z-index: 1;
}
.input {
font-size: 16px;
width: 245px;
padding: 5px 10px;
border: 0;
background-color: #FFEBBF;
position: relative;
z-index: 1;
}
.suggestions {
list-style-type: none;
margin: 0;
padding: 5px 10px;
width: 245px;
background-color: #85DDFF;
display: none;
}
.content {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
padding: 35px 10px 5px 10px;
overflow: auto;
z-index: 0;
}
input:focus ~ .autosuggest .suggestions {
display: block;
}
<div class="container">
<input class="input" type="text" value="input">
<div class="autosuggest">
<ul class="suggestions">
<li>suggestion 1</li>
<li>suggestion 2</li>
<li>suggestion 3</li>
<li>suggestion 4</li>
<li>suggestion 5</li>
<li>suggestion 6</li>
<li>suggestion 7</li>
<li>suggestion 8</li>
<li>suggestion 9</li>
</ul>
</div>
<div class="content">
content content content content content content content content content content
content content content content content content content content content content
content content content content content content content content content content
content content content content content content content content content content
content content content content content content content content content content
content content content content content content content content content content
</div>
</div>
<div class="container">
<input class="input" type="text" value="input">
<div class="autosuggest">
<ul class="suggestions">
<li>suggestion 1</li>
<li>suggestion 2</li>
<li>suggestion 3</li>
<li>suggestion 4</li>
<li>suggestion 5</li>
</ul>
</div>
<div class="content">
content content content content content content content content content content
content content content content content content content content content content
content content content content content content content content content content
</div>
</div>
¿Por qué no simplemente sacar los elementos ul y li del contenedor div y luego mover las sugerencias hacia arriba estableciendo una posición superior negativa?
http://jsbin.com/ficalu/edit?html,css,output
Actualización: Cambiar .autosuggest a posición: absoluto
Agregue esto a su CSS:
.input:focus + .suggestions {
position: fixed;
display: block;
}
Y agregue display: none;
a .suggestions
en tu CSS.
Violín here .
Esto parece un poco torpe y tiene una pequeña advertencia, pero se trata simplemente de modificaciones de estructura CSS / no HTML.
Esencialmente, hago que el .container
el padre principal en lugar de tratar de trabajar desde un nivel inferior ( .autosuggest
). Paso a paso:
-
position: relative
movimientoposition: relative
hasta.container
- Haga que
.autosuggest
posicione absolutamente (por defecto arriba / izquierda a 0px).- Dale un índice z más alto para que siempre esté arriba
- haga que
.content
posicione absolutamente los cuatro lados 0px para que tenga el mismo tamaño que.container
- Mueva la barra de desplazamiento de desbordamiento a la div
.content
- (Aquí está la advertencia) Establezca el relleno superior de
.content
a la altura de.input
+ el relleno realmente deseado. De lo contrario, el.content
está detrás del elemento de entrada.
Y terminas con esto:
.container {
height: 100px;
width: 300px;
margin-top: 50px;
border: 1px solid black;
position: relative;
}
.autosuggest {
width: 250px;
position: absolute;
z-index: 50;
}
.input {
font-size: 16px;
width: 230px;
padding: 5px 10px;
border: 0;
background-color: #FFEBBF;
}
.autosuggest .input:focus ~ .suggestions{
display: block;
}
.suggestions {
display: none;
list-style-type: none;
margin: 0;
padding: 5px 10px;
width: 230px;
background-color: #85DDFF;
}
.content {
overflow-y: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 28px 10px 5px;
}
<div class="container">
<div class="autosuggest">
<input class="input" type="text" value="input">
<ul class="suggestions">
<li>suggestion 1</li>
<li>suggestion 2</li>
<li>suggestion 3</li>
<li>suggestion 4</li>
<li>suggestion 5</li>
<li>suggestion 6</li>
<li>suggestion 7</li>
<li>suggestion 8</li>
<li>suggestion 9</li>
</ul>
</div>
<div class="content">
content content<br >content content content content content<br ><br ><br ><br ><br ><br >content content content
</div>
</div>
También agregué algunos mostrando / ocultando para el cuadro autosuggest, porque se ve bien.
.autosuggest .input:focus ~ .suggestions{
display: block;
}
.suggestions {
display: none;
}
Probado FF 43, Chrome 47
Al desplazar el contenedor, la entrada y las sugerencias deben moverse juntas.
Es muy probable que esto requiera JavaScript. Por definición, al establecer las sugerencias en posición absoluta, se eliminan del resto del flujo de contenido. Podrías establecer una altura en .suggestions
div y desplazarla por separado, pero ese desplazamiento no puede (que yo sepa) estar vinculado al desplazamiento .content
si está posicionado absolutamente (de nuevo, usando solo CSS).
Algo como:
$(''.content'').on(''scroll'', function () {
$(''.autosuggest .suggestions'').scrollTop($(this).scrollTop());
});
¿Por qué las sugerencias absolutamente posicionadas afectan la barra de desplazamiento del contenedor?
Técnicamente hablando, los elementos absolutamente posicionados no afectan la altura de los padres. Sin embargo, todavía se ven como contenido del elemento, contenido que se desborda (al menos en este caso).
La propiedad de desbordamiento especifica si se debe recortar contenido, representar barras de desplazamiento o simplemente mostrar contenido cuando se desborda su contenedor de nivel de bloque. ( de MDN )
Como .container
tiene un desbordamiento configurado para desplazarse, muestra una barra de desplazamiento porque uno de sus hijos desborda el cuadro delimitador. Si cambia el desbordamiento a oculto, ocultará todo el contenido extendido y se establecerá en visible, verá que el .autosuggest
extiende más allá del .container
, pero también lo hace .content
(ya que también es el contenido que amplía el cuadro delimitador).
Verá una barra de desplazamiento porque el contenido .suggest
se extiende visualmente más allá del bloque .container
, aunque esté posicionado de forma absoluta.
Fácil, quitar
position: relative
de la clase .autosuggest y agregar a la clase .container
Qué tal esto:
- mover contenedor exterior autosugerido
- dé al contenido el mismo margen que la altura de entrada (si está utilizando MENOS / SASS, debería poder calcularlo)
- soltar el autosugestión para ocupar el espacio del margen
Mis cambios en el CSS tienen un comentario al lado de ellos. Tenga en cuenta que esto solo se probó en Chrome. También es probable que pueda optimizar el HTML un poco, como eliminar el contenedor en el ejemplo, pero probablemente tenga varios elementos allí.
el HTML:
<div class="autosuggest">
<input class="input" type="text" value="input">
<ul class="suggestions">
<li>suggestion 1</li>
<li>suggestion 2</li>
<li>suggestion 3</li>
<li>suggestion 4</li>
<li>suggestion 5</li>
<li>suggestion 6</li>
<li>suggestion 7</li>
<li>suggestion 8</li>
<li>suggestion 9</li>
</ul>
</div>
<div class="container">
<div class="content">
content content content content content content content content content content
</div>
</div>
el CSS:
.container {
height: 100px;
width: 300px;
overflow-y: auto;
border: 1px solid black;
}
.autosuggest {
position: relative;
top:29px; /* height of input */
left:1px; /* width of container border */
width: 250px;
}
.input {
font-size: 16px;
width: 230px;
padding: 5px 10px;
border: 0;
background-color: #FFEBBF;
}
.suggestions {
list-style-type: none;
margin: 0;
padding: 5px 10px;
width: 230px;
background-color: #85DDFF;
position: absolute;
}
.content {
width: 120px;
margin-top: 29px; /* height of input */
padding: 5px 10px;
}
Todo lo que tienes que hacer es agregar las propiedades del índice z a .autosuggest y .suggestions aquí es un ejemplo de código de codepen
http://codepen.io/HTMLNoob/pen/EPEXKN
.autosuggest {
z-index: -10;
width: 250px;
}
.suggestions {
list-style-type: none;
margin: 0;
padding: 5px 10px;
width: 230px;
background-color: #85DDFF;
position: absolute;
z-index: 10;
}
ACTUALIZAR:
creo que esto es lo que estás buscando
http://jsbin.com/fegibaboyo/1/edit?html,css,output
Nota: Desplácese sobre la entrada con sugerencias.
ACTUALIZACIÓN2:
http://jsbin.com/mojopuboku/edit?html,css,output
Aquí está la nueva respuesta.
He probado esta respuesta en la mayoría de los navegadores (Firefox, Chrome, Opera) y todos tienen los mismos resultados. (No estoy seguro acerca de Safari, porque no puedo instalar Safari en mi Windows XP)
puede hacerlo en el estilo "solo css" SOLAMENTE si los elementos de la sugerencia 1,2,3 no serán hijos del elemento "input".
por ejemplo:
<input>
content
content
</input>
suggestion1
suggestion2
suggestion3
o como ejemplo de trabajo, sugerir htmlnoob http://jsbin.com/mojopuboku/edit?html,css,output
otra solución, puede funcionar solo en navegadores antiguos, como ie5.
.autosuggest {
position: fixed; /* add position:fixed */
}
.suggestions {
/* remove position:absolute */
}