Home > OS >  How to "extract aside" an element from a vertical flexbox layout?
How to "extract aside" an element from a vertical flexbox layout?

Time:10-23

Let's say I have a couple elements arranged in a column (using flexbox): elements in a column

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:

a wider layout, with element #2 set aside

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);
    }
  • Related