Switch between these two layouts based on screen size

My app made up of three sections: top, middle and bottom. I want it to look like this when displayed on mobile (viewport size xs):

  +--------+  # mobile
  |  top   |
  |--------|
  |        |
  | middle |
  |        |
  |--------|
  | bottom |
  +--------+

And like this when displayed on desktop (viewport sizes sm-xxl):

  +--------+ +--------+  # desktop
  |  top   | |        |
  |--------| | middle |
  | bottom | |        |
  +--------+ +--------+

These two layouts are fairly straightforward to create separately:

dbc.Col([         # mobile
    dbc.Col(top),
    dbc.Col(middle),
    dbc.Col(bottom)
])

dbc.Row([                   # desktop
    dbc.Col([top, bottom]),
    dbc.Col(middle)
])

The problem is I don’t know how to create a single layout which switches between the two based on screen width. The documentation describes how the order, offset and size parameters of a dbc.Col can be used to dynamically change the layout based on the Bootstrap responsive tiers. But after a good amount of tinkering, I still can’t figure out how to achieve the switching behavior described above.

Here is a minimal code sample, along with a screenshot of the unintended result:

from dash import Dash, html
import dash_bootstrap_components as dbc

top = dbc.Col(
    html.H1('top'),
    style={'height': '10em', 'background-color': '#636EFA'}
)
middle = dbc.Col(
    html.H1('middle'),
    style={'height': '20em', 'background-color': '#EF553B'}
)
bottom = dbc.Col(
    html.H1('bottom'),
    style={'height': '8em', 'background-color': '#00CC96'}
)

layout = dbc.Row([
    dbc.Col(
        top,
        xs=dict(order=1, size=12),
        sm=dict(order=1, size=6)
    ),
    dbc.Col(
        middle,
        xs=dict(order=2, size=12),
        sm=dict(order=2, size=6)
    ),
    dbc.Col(
        bottom,
        xs=dict(order=3, size=12),
        sm=dict(order=3, size=6)
    )
])

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container(layout)
app.run_server(debug=True)

I was able to achieve it with basic HTML and CSS:

<div class="container">
  <div class="row flex-container">
    <div id="sectionT" class="col col-sm-12 col-md-6 t">Top</div>
    <div id="sectionM" class="col col-sm-12 col-md-6 m">Middle</div>
    <div id="sectionB" class="col col-sm-12 col-md-6 b">Bottom</div>
  </div>
</div>
.t {
  background-color: blue;
  height: 100px;
}

.m {
  background-color: red;
  float: right;
  height: 200px;
}

.b {
  background-color: green;
  height: 100px;
}

@media screen and (min-width: 991px) {
  .flex-container {
    display: flex;
    flex-direction: column;
    height: 300px;
    flex-wrap: wrap;
  }
  #sectionT {
    order: 1;
  }
  #sectionM {
    order: 3;
  }
  #sectionB {
    order: 2;
  }
}

What I needed was this information here: Mastering wrapping of flex items - CSS: Cascading Style Sheets | MDN

Here it says:

We can see the same thing happening with columns. The container will need to have a height in order that the items will start wrapping and creating new columns, and items will stretch taller to fill each column completely.

Thanks @yanboe, that was exactly what I needed. I included a custom stylesheet alongside my app with the media query you showed. I’ve attached the code below which produced the layout I wanted.

app.py

from dash import Dash
import dash_bootstrap_components as dbc

top = dbc.Col('top', style={'height': '10em', 'background-color': '#636EFA'})
middle = dbc.Col('middle', style={'height': '20em', 'background-color': '#EF553B'})
bottom = dbc.Col('bottom', style={'height': '8em', 'background-color': '#00CC96'})

layout = [
    dbc.Col(
        top,
        xs=dict(order=1, size=12),
        sm=dict(order=1, size=6)
    ),
    dbc.Col(
        middle,
        xs=dict(order=2, size=12),
        sm=dict(order=3, size=6)
    ),
    dbc.Col(
        bottom,
        xs=dict(order=3, size=12),
        sm=dict(order=2, size=6)
    )
]

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container(layout, className='root-container')
app.run_server(debug=True)

assets/custom.css:

@media screen and (min-width: 576px) {
    .root-container {
        display: flex;
        flex-wrap: wrap;
        flex-direction: column;
        height: 300px;
    }
}