alanbuchanan alanbuchanan - 7 months ago 19
HTML Question

Re-positioning two divs from a column format on smaller screens to a single row on wider screens

I have made a basic layout for a football scoreboard using flexbox.

The view has two separate views: large screens and small screens.

Here is what the large screen layout looks like:

enter image description here

Here is what the small screen layout looks like:

enter image description here

My question is: On the large screen layout, what is a good way for me to be able to position the

corner-a
and
corner-b
so that they are level with the
carded-players
row, while maintaining the layout on small screens?


The struggle I have experienced with this is that on small screens, it feels like I should wrap the two
corner
divs in their own
corners
wrapper, as is the case at the moment. On large screens, it feels like the two divs should not have a
corners
wrapper and just sit on their own in the corners of the
wrap
container.

What is a good way to solve this, without duplicating HTML?

CSS (compiled from SCSS):

@media (min-width: 601px) {
.desktop-hide {
display: none !important;
}
}

@media (max-width: 600px) {
.mobile-hide {
display: none !important;
}
}

* {
box-sizing: border-box;
}

.wrapper {
border: 1px solid seagreen;
max-width: 800px;
display: flex;
flex-flow: column wrap;
align-items: center;
}

.main {
display: flex;
flex-flow: row;
max-width: 600px;
min-width: 550px;
border: 1px solid orangered;
}

.timer {
display: flex;
justify-content: center;
}

.left-col, .right-col {
max-width: 300px;
}

* {
box-sizing: border-box;
}

.team {
background: chartreuse;
}

.score {
background: brown;
}

.scorers {
background: steelblue;
}

.cards-desktop {
background: goldenrod;
}

.carded-players {
background: darkorange;
}

.left-col, .right-col {
width: 80%;
margin: auto;
}

.left-col * >, .right-col * > {
display: flex;
}

.top > div {
padding: 5px;
}

.bottom > div {
height: 25px;
}

.top {
display: flex;
flex-flow: column wrap;
height: 100px;
}

.team,
.scorers {
height: 50%;
width: 75%;
}

.score {
width: 25%;
display: flex;
flex: 0 0 100%;
align-items: center;
justify-content: center;
font-size: 28px;
}

@media (max-width: 600px) {
.main {
min-width: 100%;
}

.top {
flex-flow: column nowrap;
height: initial;
}

.team, .scorers {
height: initial;
width: 100%;
}

.score {
flex: 1 100px;
align-self: flex-end;
}

.scorers {
order: 1;
}
}

.right-col .score {
align-self: flex-end;
}

.right-col .top {
flex-flow: column wrap-reverse;
}

.left-col .top > *:not(.score), .left-col .bottom > * {
display: flex;
justify-content: flex-end;
}

.team, .scorers {
display: flex;
align-items: center;
}

.empty {
height: 28px;
}

.colon {
height: 95px;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}

.corners {
display: flex;
flex-flow: row;
width: 100%;
justify-content: space-between;
}

.corner-left, .corner-right {
border: 1px solid crimson;
}


Codepen link: http://codepen.io/alanbuchanan/pen/dMgJZg?editors=1100

Answer

The layout you want is possible with a combination of CSS positioning and media queries.

First, you can get rid of all this unnecessary code:

duplicate html (desktop and mobile versions)

<!-- REMOVE
<div class="corner-a mobile-hide">corner a</div>
<div class="corner-b mobile-hide">corner b</div>
<div class="corners desktop-hide">
     <div class="corner-left">corner-a</div>
     <div class="corner-right">corner-b</div>
</div>
-->

As suggested in your question, using duplicate HTML is not an optimal solution.

also remove obsolete css

/* 
@media (min-width: 601px) {
     .desktop-hide {
          display: none !important;
     }
}
@media (max-width: 600px) {
     .mobile-hide {
          display: none !important;
     }
}
*/

Second, add the corner elements as the last child of .left-col and .right-col.

<div class="left-col">
     <div class="top"> ...  </div>
     <div class="bottom"> ...  </div>
     <div class="corner-a">corner a</div><!-- new location -->
</div>

<div class="right-col">
     <div class="top"> ...  </div>
     <div class="bottom"> ...  </div>
     <div class="corner-b">corner b</div><!-- new location -->
</div>

Third, enable the corners to accept flex properties by making the parents flex containers:

.left-col,
.right-col {
     display: flex;               /* new */
     flex-direction: column;      /* new */
     max-width: 300px;
     width: 80%;
     margin: auto;
}

Fourth, style the corners for smaller screens:

@media (max-width: 600px) {

     .corner-a {
          align-self: flex-start;
          position: static;
     }

     .corner-b {
          align-self: flex-end;
          position: static;
     }

}

Fifth, style the corners for wider screens.

.wrapper {
     border: 1px solid seagreen;
     max-width: 800px;
     display: flex;
     flex-flow: column wrap;
     align-items: center;
     position: relative;    /* new */
}

.corner-a {
     position: absolute;
     left: 0;
     bottom: 0;
  }

.corner-b {
     position: absolute;
     right: 0;
     bottom: 0;
}

NOTES:

  • For smaller screens, the corners are positioned in the layout per the document flow. They are aligned with flex properties.

  • For wider screens the corners are removed from the document flow with absolute positioning. They are then positioned within their container (defined as the element which is the nearest positioned ancestor). This would be .wrapper. On smaller screens the corners are restored to the normal flow with position: static.

Revised Codepen