Let's say I have a couple elements arranged in a column (using flexbox):
And I would like to "spotlight" element #2 in green and set it aside, but let the rest of the elements remain ordered in a column:
Is there a way to do this with just CSS and retain dynamic layout?
I've thought of a workaround by duplicating the green element and wrapping all of this in another flexbox layout ([2[1234]]
) so that in the column case, the first green element is hidden ([#[1234]
) whereas in the wider case, the second element is hidden ([2[1#34]
), but this is a bit messy in the markup - and actually causes issues when the element has some kind of state (e.g. a <video>
) that is expected to be retained in both cases.
I've also thought about using position: absolute
on the green element, but I couldn't get that to work nicely either: once I set position: relative
on the top-level (black) container, I can position the green element where I want, but setting position: absolute
on the column container (red) so that I can position in to the right means green element is now positioned relative to the column container again.
Is there a solution I'm overlooking?
CodePudding user response:
if you want, i can answer this, but not using flexbox, using Grid.
CodePudding user response:
const expand = document.querySelector('.expand');
expand.addEventListener('click', () => {
expand.parentNode.classList.toggle('active');
});
body {
margin: 0;
}
aside {
display: flex;
flex-direction: column;
gap: 1em;
flex-wrap: wrap;
width: 50vw;
height: 100vh;
background-color: rgba(0, 0, 0, .1);
padding: 1em;
box-sizing: border-box;
position: relative;
transition: .2s;
}
div {
flex: 1;
background-color: rgba(0, 0, 0, .1);
display: flex;
justify-content: center;
align-items: center;
order: unset;
}
.expand {
position: absolute;
right: 0;
top: 50%;
transform: translate(50%, -50%);
padding: 0;
display: flex;
border: none;
background-color: #ddd;
border-radius: 100%;
width: 24px;
height: 24px;
box-shadow: 0 0 0 3px white;
}
.expand svg {
margin: auto;
border-radius: 100%;
transition: .2s;
}
aside.active {
width: 90vw;
}
.active .expand svg {
transform: rotate(180deg);
}
.active .two {
flex: 100 0 100%;
order: -1;
}
<aside >
<button >
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M12 0c6.623 0 12 5.377 12 12s-5.377 12-12 12-12-5.377-12-12 5.377-12 12-12zm0 1c6.071 0 11 4.929 11 11s-4.929 11-11 11-11-4.929-11-11 4.929-11 11-11zm-3 5.753l6.44 5.247-6.44 5.263.678.737 7.322-6-7.335-6-.665.753z"/></svg>
</button>
<div >1</div>
<div >2</div>
<div >3</div>
<div >4</div>
</aside>
CodePudding user response:
Yes you can do this using just CSS. Here's the code for the answer to your question. HTML:
<div >
<div >
</div>
<div >
<div >1</div>
<div >2</div>
<div >3</div>
<div >4</div>
<div >5</div>
</div>
</div>
CSS:
.gridcontainer{
display: grid;
background: yellow;
grid-template-columns: 1fr .5fr;
height: 20em;
}
.flexcontainer{
background: skyblue;
padding: .5em;
grid-column: 2;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.card{
background: pink;
border: .1em solid red;
width: 80%;
padding: 1em;
text-align: center;
}
.flexcontainer .card:hover{
position: absolute;
width: 45%;
height: 15em;
transform: translateX(-50vw) translateY(1vh);
}