Home > database >  2 column layout until first column height is done and then one column layout
2 column layout until first column height is done and then one column layout

Time:01-24

My webpage has a 2 column layout, left side is filters and right side is articles, like this: 2 column layout

Goals:

  • Fixed width filters (left side) @ big viewport
  • Full width filters above articles (one column layout) @ small viewport
  • @ big viewport stack articles on right till we get to the height end of 1st column and then full width articles, like this:

End of 2 column layout

I am currently doing this with JS getBoundingClientRect() but would love to know if there is a CSS solution please?!

As requested, current JS solution via SvelteKit:

import {
  onMount
} from 'svelte';
import type {
  PageData
} from './$types'
import Source from '$lib/components/Source.svelte'
import type {
  QuoteCategory
} from '$lib/util/types'
import AuthorChips from '$lib/components/chips/AuthorChips.svelte'
import QuoteCategoryChips from '$lib/components/chips/QuoteCategoryChips.svelte'

export let data: PageData
let categories: QuoteCategory[]
if (data.categories) categories = data.categories

onMount(fullSizeSources)

function fullSizeSources() {
  let wideDone = false
  const scrollTop = document.documentElement.scrollTop
  const authors = document.getElementById('author-chips')
  const sources = document.getElementsByClassName('source')
  const authorBottom = (authors ? .getBoundingClientRect() ? .bottom || 0)   scrollTop

  for (let source of sources) {
    if (wideDone || (source.getBoundingClientRect().top   scrollTop) > authorBottom) {
      wideDone = true
      source.classList.add('full')
    } else {
      source.classList.remove('full')
    }
  }
}
.wrapper {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  .left {
    max-width: 36rem;
    margin-right: 1.8rem;
    display: flex;
    flex-direction: column;
  }
   :global(.source.full) {
    margin-left: -37rem;
    width: calc(100%   37rem);
  }
}
<div >
  <div >
    { #if data.categories }
    <QuoteCategoryChips categories={ data.categories } location="nav" /> { /if } { #if data.authors }
    <AuthorChips authors={ data.authors } /> { /if }
  </div>

  <div>
    { #if data.sources } { #each data.sources as source }
    <Source { source } /> { /each } { /if }
  </div>
</div>

CodePudding user response:

If I understand you correctly, you can solve this problem by using float and @media. For small viewport use normal layout with one column. For big viewport you can use float: left; so that your articles are on the right side and after reaching the height of the left column they become 100% width.

/* Just some styles to visualise. Notice the use of flex, it makes it easier to work with the content of these elements */

.left,
.right-article {
  display: flex;
  flex-direction: column;
  padding: 1rem;
  margin: 1rem;
  border: 1px solid blue;
}


/* Replace 600px with whatever you need */

@media (min-width: 600px) {
  .left {
    /* Replace the width with whatever you need */
    width: 300px;
    float: left;
  }
}
<div>
  <div >
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Exercitationem et qui fuga non illo nemo, harum ab, vero in illum maxime, dolore dignissimos velit provident id iure accusantium fugiat amet!</p>
  </div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit..</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>
  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit..</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>
  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit..</div>

  <div >Lorem ipsum, dolor sit amet consectetur adipisicing elit.</div>
</div>

  • Related