¿Sabes ese sentimiento cuando creas tu propio componente en lugar de mejorar los componentes HTML predeterminados? tu equipo de diseño creó algo hermoso, pero los navegadores no lo soportarán fuera de la caja, y arreglarlo en todas partes se convierte en una pesadilla. Hoy quería hablar de una trampa que nos espera durante este emocionante viaje: la colocación de elementos descartados, como los menús seleccionados o los seleccionadores de fechas. Absolutamente equivocado Al principio, parece resuelve todos nuestros problemas, y lo hace hasta cierto punto. position: absoluto Posición: absoluto Si la caída se sobrecarga, se corta.Seguramente, puede desplazarse hacia abajo y verlo, pero es mejor orar para que su diseñador no pueda llegar a usted con un objeto agudo. Esto está lejos de ser perfecto, podemos hacerlo mejor. Fix It With 'fixed' 'fixado' Si queremos mostrar el contenido sobre todo, necesitamos . El único problema es que perderemos las coordenadas del elemento principal: los elementos fijos son bastante independientes por naturaleza. Esto significa que lo único que necesitamos hacer es determinar las coordenadas exactas del elemento descendente en estas situaciones: posición: fijo posición: fijo Cuando lo mostramos. Cuando se cambia su contenido. Cuando se desplaza la ventana y/o el parente deslizable. Cuando se desplaza la ventana y/o el parente deslizable. Cuando lo mostramos. Cuando se cambie su contenido. Cuando desplazamos la ventana y/o el parente desplazable. Cuando cambiamos el tamaño de la ventana y/o el parente deslizable. También necesitamos decidir si lo mostraremos por encima del tomador si está demasiado cerca de la parte inferior de la pantalla. Usaré Vue.js, pero debe ser fácil de seguir incluso si prefiere React o Angular. Let’s Rock This Joint Aquí está la estructura que vamos a usar: export const useDropdownAttributes = () => { const dropdownWidth = ref(''); const dropdownTop = ref(''); const dropdownBottom = ref(''); const dropdownLeft = ref(''); const isDirectedUpwards = ref(false); const togglerRect = ref<DOMRect>(); const dropdownRect = ref<DOMRect>(); const autodetectPosición = ( isDropdownDisplayed: Ref<boolean>), togglerElement: HTMLE TNT null = null, dropdownElement: HTMLDivementElement null = null, dropdownContent: Ref<nunkown export const useDropdownAttributes = () => { const dropdownWidth = ref(''); const dropdownTop = ref(''); const dropdownBottom = ref(''); const dropdownLeft = ref(''); const isDirectedUpwards = ref(false); const togglerRect = ref<DOMRect>(); const dropdownRect = ref<DOMRect>(); const autodetectPosición = (es DropdownDisplayed: Ref<boolean>;, togglerElement: HTMLE torglement null = null, dropdownElement: HTMLDivementEl torget null = null, dropdownContent: Ref<nunk DropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDropDrop Hay cuatro variables para la posición de descarga más la bandera y una función que las actualiza todas.También devuelven dos variables para el toggler y las rectas de descarga: esto podría ser conveniente, por ejemplo, para las pistas de herramientas que deben alinearse con el medio del contenido. isDirectedUpwards esDirectado hacia arriba Como usted puede recordar, también necesitamos manejar el desplazamiento y el desplazamiento del parente desplazable, así que creemos una función para encontrarlo: const getFirstScrollableParent = (element: HTMLElementintza null): HTMLElement => {const parentElement = element?.parentElement; si (!parentElement) devuelve document.body; const overflowY = window.getComputedStyle(parentElement).overflowY; si (overflowY ==='scroll' Átha overflowY === 'auto') devuelve parentElement; devuelve getFirstScrollableParent(parentElement); }; const getFirstScrollableParent = (element: HTMLElementannoo null): HTMLElement => { const parentElement = element?.parentElement; si (!parentElement) devuelve document.body; const overflowY = window.getComputedStyle(parentElement).overflowY; si (overflowY ==='scroll' Gaill overflowY === 'auto') devuelve parentElement; devuelve getFirstScrollableParent(parentElement); }; Ahora, añadamos la función principal: Pasamos y para que podamos reaccionar a sus actualizaciones. isDropdownDisplayed dropdownContent esDropdownDisplayed DropdownContenido También pasamos y que necesitamos para calcular la posición. togglerElement dropdownElement TogglerElemento DropdownElemento Finalmente, hay en caso de que desee la caída por encima del toggler por defecto. isUpwardPreferred esPrefiero Tiempo para relajarse y disfrutar En su componente, necesitará algo así (supongo que ha añadido refs a su toggler y dropdown en la plantilla): const { autodetectPosición, dropdownTop, dropdownBottom, dropdownLeft, dropdownWidth, isDirectedUpwards, } = useDropdownAttributes(); const togglerRef = ref<HTMLElement>(); const dropdownRef = ref<HTMLElement>(); const esDropdownShown = ref(false); onMounted(() => { autodetectPosition(isDropdownShown, togglerRef.value?.$el, dropdownRef.value?.$el); } const { autodetectPosición, dropdownTop, dropdownBottom, dropdownLeft, dropdownWidth, isDirectedUpwards, } = useDropdownAttributes(); const togglerRef = ref<HTMLElement>(); const dropdownRef = ref<HTMLElement>(); const esDropdownShown = ref(false); onMounted(() => { autodetectPosition(isDropdownShown, togglerRef.value?.$el, dropdownRef.value?.$el); } Y el CSS se verá así: .dropdown { posición: fija; abajo: v-bind('esDirectedUpwards? dropdownBottom : dropdownTop'); izquierda: v-bind('dropdownLeft'); anchura: v-bind('dropdownWidth'); min-width: 0; } .dropdown { posición: fija; abajo: v-bind('isDirectedUpwards? dropdownBottom : dropdownTop'); izquierda: v-bind('dropdownLeft'); anchura: v-bind('dropdownWidth'); min-width: 0; } Voilà. La caída se muestra correctamente incluso cuando se sobrecarga y se mueve por encima del toggler si no hay suficiente espacio debajo. Y ya que estamos al final del artículo, me encantaría dejarte con algo alegre, pero estoy fuera de ideas. Puede encontrar el código completo en . GitHub Puede encontrar el código completo en . GitHub GitHub