Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

151
Views
¿Cómo hacer que un cuadro se expanda y pase del origen al centro de la pantalla sin afectar el DOM?

Estoy tratando de hacer que un cuadro se expanda (en ancho y alto) y pase de su origen al centro de una pantalla al hacer clic. Esto es lo que tengo hasta ahora:

Me encuentro con dos problemas aquí: cuando hago clic en el cuadro, el DOM cambia automáticamente, porque el elemento en el que se hizo clic tiene su posición cambiada a 'absolute' . El otro problema es que el cuadro no hace la transición desde su origen, hace la transición desde la esquina inferior derecha (tampoco regresa a su posición desde el centro de la pantalla, cuando se hace clic en make inactive ).

¿Qué estoy haciendo mal aquí?

 import React from "react"; import styled from "styled-components"; import "./styles.css"; export default function App() { const [clickedBox, setClickedBox] = React.useState(undefined); const handleClick = React.useCallback((index) => () => { console.log(index); setClickedBox(index); }); return ( <Container> {Array.from({ length: 5 }, (_, index) => ( <Box key={index} active={clickedBox === index} onClick={handleClick(index)} > box {index} {clickedBox === index && ( <div> <button onClick={(e) => { e.stopPropagation(); handleClick(undefined)(); }} > make inactive </button> </div> )} </Box> ))} </Container> ); } const Container = styled.div` display: flex; flex-wrap: wrap; align-items: center; height: 100vh; `; const Box = styled.div` flex: 1 0 32%; padding: 0.5rem; cursor: pointer; margin: 1rem; border: 1px solid red; transition: 2s; background-color: white; ${({ active }) => ` ${ active ? ` position: absolute; width: 50vw; height: 50vh; background-color: tomato; top: 50%; left: 50%; transform: translate(-50%, -50%); ` : "" } `} `;

relajado-galois-iypsj

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

Con CSS

Es muy poco probable que puedas lograr eso con css simple. Y seguro imposible lograr una solución versátil.

  • Tiene un tamaño dinámico y una posición para adoptar (div inicial)
  • Tienes que adaptarte a la posición de desplazamiento actual
  • Si elimina el div del diseño, es casi imposible evitar arruinar el diseño (incluso si puede, siempre habrá algún caso extremo).
  • transición de una posición relative a una fixed .

Con el estándar css actual es imposible realizar estas cosas.

con JS

La solución es hacer algo de magia javascript . Como está usando React , le desarrollé una solución usando react-spring (un marco de animación). Aquí tienes un componente de envoltura que hará lo que quieras:

El SandBox completo

 import React, { useEffect, useRef, useState } from "react"; import { useSpring, animated } from "react-spring"; export default function Popping(props) { const cont = useRef(null); const [oriSize, setOriSize] = useState(null); const [finalSize, setFinalSize] = useState(null); useEffect(() => { if (props.open && cont.current) { const b = cont.current.getBoundingClientRect(); setOriSize({ diz: 0, opacity: 0, top: b.top, left: b.left, width: b.width, height: b.height }); const w = window.innerWidth, h = window.innerHeight; setFinalSize({ diz: 1, opacity: 1, top: h * 0.25, left: w * 0.25, width: w * 0.5, height: h * 0.5 }); } }, [props.open]); const styles = useSpring({ from: props.open ? oriSize : finalSize, to: props.open ? finalSize : oriSize, config: { duration: 300 } }); return ( <> <animated.div style={{ background: "orange", position: "fixed", display: styles.diz?.interpolate((d) => (d === 0 ? "none" : "initial")) || "none", ...styles }} > {props.popup} </animated.div> <div ref={cont} style={{ border: "2px solid green" }}> {props.children} </div> </> ); }

Nota: este código usa dos <div> , uno para envolver su contenido y el segundo siempre está fixed pero oculto. Cuando cambia la visibilidad de la ventana emergente, se mide el div envolvente (obtenemos su tamaño y posición en la pantalla) y el div fixed se anima desde esa posición hasta su posición final. Puede lograr la ilusión que está buscando renderizando el mismo contenido en ambos <div> , pero siempre existe el riesgo de una desalineación menor.

about 4 years ago · Juan Pablo Isaza Report

0

La idea es similar a lo que hizo el novato en su publicación, pero sin bibliotecas adicionales. Podría haber hecho algunas cosas un poco no estándar para evitar el uso de bibliotecas.

CódigoSandbox

 import React from "react"; import { StyledBox } from "./App.styles"; export const Box = (props) => { const boxRef = React.useRef(null); const { index, active, handleClick } = props; const handleBoxClick = () => { handleClick(index); }; React.useEffect(() => { const b = boxRef.current; const a = b.querySelector(".active-class"); a.style.left = b.offsetLeft + "px"; a.style.top = b.offsetTop + "px"; a.style.width = b.offsetWidth + "px"; a.style.height = b.offsetHeight + "px"; }); return ( <StyledBox active={active} onClick={handleBoxClick} ref={boxRef}> box {index} <div className="active-class"> box {index} <div> <button onClick={(e) => { e.stopPropagation(); handleClick(undefined); }} > make inactive </button> </div> </div> </StyledBox> ); };
 import styled from "styled-components"; export const StyledContainer = styled.div` display: flex; flex-wrap: wrap; align-items: center; height: 100vh; `; export const StyledBox = styled.div` flex: 1 0 32%; padding: 0.5rem; cursor: pointer; margin: 1rem; border: 1px solid red; background-color: white; .active-class { position: absolute; transition: 0.3s all ease-in; background-color: tomato; z-index: -1; ${({ active }) => active ? ` width: 50vw !important; height: 50vh !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%); z-index: 1; opacity: 1; ` : ` z-index: -1; transform: translate(0, 0); opacity: 0; `} } `;
about 4 years ago · Juan Pablo Isaza Report

0

primero, la transición con posición o visualización no funciona en css (puede funcionar pero sin transición).

aquí tienes:

 flex: 1 0 32%;

que es equivalente a:

 flex-grow: 1; flex-shrink: 1; flex-basis: 32%;

entonces, cuando activo es verdadero , el ancho saltaría a 50vw y la altura a 50vh pero aproximadamente sin transición. entonces la solución es usar una escala como esta:

 z-index: 99; transform: scaleY(5) scaleX(2) translate(20%, 20%); background-tomato: tomato

y necesita modificar los valores de scaleY , scaleX y translate (para cada Box) hasta que funcione.

puedes echar un vistazo a lo que hice en este codesandbox: https://codesandbox.io/s/peaceful-payne-ewmxi?file=/src/App.js:1362-1432

aquí también hay un enlace si quieres master flex: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Controlling_Ratios_of_Flex_Items_Along_the_Main_Ax

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!