Align <video> center of flexbox with variable height - css

I have a video page with 3 primary elements (header, video, settings footer). The settings footer is collapsable.
I am happy with the layout when the settings footer is visible, but I wish I could increase the size of the video to take up the remaining height once the settings footer is collapsed. In other words, the video should grow in size slightly on footer collapse.
Here is what I have so far:
var el = document.getElementsByClassName("settings-container")[0];
el.addEventListener("click", function(e) {
e.target.classList.toggle("collapsed");
});
body {
font-size: 16px;
}
.main-container {
display: flex;
flex-direction: column;
min-height: 100vh;
overflow: hidden;
}
.header-container {
align-items: center;
border-bottom: 0.0625rem solid #b2b2b2;
display: flex;
flex: 0 0 1.938rem;
padding: .25rem .9375rem;
}
.video-container {
align-items: center;
display: flex;
flex: 1 1 auto;
justify-content: center;
padding: .9375rem;
}
.video-container .video-player {
border: 0.1875rem solid black;
display: flex;
overflow: hidden;
position: relative;
}
my-video-player {
background-color: transparent;
display: block;
font-family: arial, sans-serif;
font-size: 12px;
position: relative;
}
my-video-player .video video {
height: auto;
max-height: calc(100vh - 19.75rem);
max-width: 100%;
width: auto;
}
.settings-container {
background: #f4f4f4;
display: flex;
flex: 0 1 15rem;
flex-direction: column;
position: relative;
top: 0;
transition: flex .5s;
}
.settings-container.collapsed {
flex: 0 0 2.4rem;
}
<div class="main-container">
<div class="header-container">Header</div>
<div class="video-container">
<div class="video-player">
<my-video-player>
<div class="video">
<video autobuffer controls>
<source id="mp4" src="http://footage.framepool.com/mov/521-436-838.mp4" type="video/mp4">
</video>
</div>
</my-video-player>
</div>
</div>
<div class="settings-container">Settings - click me to collapse</div>
</div>
Best viewed in fullscreen!
I am looking for a css-only solution where the video takes up the available space between the header and the footer. Right now I have hard-coded a max-height to the video element to make it fit, but my attempts to solve this otherwise have failed.
I have already seen posts suggesting position: absolute and relative to the child and parent respectively, but the many levels of flexbox is making this hard for me.
Thankful for any ideas or suggestions.

Related

An alternative design without a scrollbar caused by padding

The code that appears below creates the following layout:
The important part is that the content, although centered on the screen when not overflowing, never overlaps the navbar and has its own scrollbar:
The problem is that this layout is achieved with the help of padding (marked by a comment in the code below), which results in the additional scrollbar on the right of the screen.
How can I design the same layout that would have only one scrollbar - the one in the content?
Please note that the solution should not break the following details:
The rounded corners and the shadow.
The title in the content block not participating in scrolling.
The image covering the whole scrollable content, so it scrolls together with the content.
In addition, it would be great if this can be achieved without as many nested div's as I have right now.
Edit: I am ready to go with the suggestion of #JHeth in the comments section. However, I would still be interested if someone can come up with an alternative design that does not rely on padding for centering.
Here is the code (CodePen):
* {
padding: 0;
margin: 0;
}
html {
font-size: 62.5%;
}
:root {
--navbar-height: 3rem;
}
.navbar {
width: 100%;
text-align: center;
font-size: 2rem;
line-height: var(--navbar-height);
background-color: lightgreen;
}
.centering {
position: absolute;
inset: var(--navbar-height) 0 0 0;
display: flex;
flex-direction: column;
align-items: center;
& .auto-margin {
margin: auto;
// For scrollable content
display: flex;
max-height: 100%;
padding-bottom: calc(var(--navbar-height)); // Causes scrolling
}
}
.content-block {
display: flex;
flex-direction: column;
.title {
font-size: 2rem;
position: sticky;
}
.content-outer-container {
display: flex;
flex-direction: column;
overflow-y: auto;
border-radius: 1em;
box-shadow: 0 1em 2em rgba(black, 0.4);
.content-container {
width: 300px;
overflow-y: auto;
.content {
position: relative;
padding: 1em;
&:before {
content: "";
z-index: -1;
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background-position: center;
background-image:
url(http://www.freegreatpicture.com/files/147/18380-hd-color-background-wallpaper.jpg);
}
}
}
}
}
<div class="navbar">An Amazing Navbar</div>
<div class="centering">
<div class="auto-margin">
<div class="content-block">
<div class="title">My Title</div>
<div class="content-outer-container">
<div class="content-container">
<div class="content">
<h1>Line1</h1>
<h1>Line2</h1>
<h1>Line3</h1>
<h1>Line4</h1>
<h1>Line5</h1>
</div>
</div>
</div>
</div>
</div>
</div>
simply remove max-height:100%; to .centering .auto-margin and it'll works!
.centering .auto-margin {
margin: auto;
display: flex;
/* max-height: 100%; */
padding-bottom: calc(var(--navbar-height));
}

two-column sticky flexbox scrolling not working [duplicate]

This question already has an answer here:
Why is 'position: sticky' not working with Core UI's Bootstrap CSS
(1 answer)
Closed 1 year ago.
I'm having trouble getting my flexbox two-column setup to work.
Basically I just want the left column to be sticky while scrolling down the right one and then end scrolling at the exact same point.
It should also be collapsible as in the example below.
It's supposed to substitute this solutions i made using a regular grid which I'm unfortunately not able use anymore.
You can see my current progress below - I'm not really able to figure out what to do from here - as I'm a rookie I hoped you guys would know.
.wrapper {
display: flex;
flex-flow: row wrap;
overflow: auto;
gap: 2em;
justify-content: flex-start;
height: auto;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.aside-1 {
position: -webkit-sticky;
position: sticky;
background: gold;
height: auto;
top: 0;
align-self: flex-start;
}
.aside-2 {
background: hotpink;
height: 900px;
top: 0;
}
#media all and (min-width: 300px) {
.aside { flex: 1 0 0; }
}
<section class="page-width">
<div class="wrapper">
<aside class="aside aside-1"><img width="100%" src="https://cdn.shopify.com/s/files/1/0044/2852/9698/files/242370040_4238706352865614_2798039132201744827_n.jpg"> Aside 1
</aside>
<aside class="aside aside-2">
Aside 2
</aside>
</div>
</section>
I've checked the forum without really finding what I need and hope that somebody would be able to help me :o) Thanks a million!
Remove overflow:auto on parent container of sticky element to make stickiness work
.wrapper {
display: flex;
flex-flow: row wrap;
gap: 2em;
justify-content: flex-start;
height: auto;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.aside-1 {
position: -webkit-sticky;
position: sticky !important;
background: gold;
top: 0 !important;
align-self: flex-start;
}
.aside-2 {
background: hotpink;
height: 900px;
top: 0;
}
#media all and (min-width: 300px) {
.aside { flex: 1 0 0; }
}
.other-content{
margin-top: 2rem;
height: 20rem;
width: 100%;
background: red;
position:sticky;
top:0;
}
<section class="page-width">
<div class="wrapper">
<aside class="aside aside-1"><img width="100%" src="https://cdn.shopify.com/s/files/1/0044/2852/9698/files/242370040_4238706352865614_2798039132201744827_n.jpg"> Aside 1
</aside>
<aside class="aside aside-2">
Aside 2
</aside>
</div>
<div class="divider"></div>
<div class="other-content"></div>
</section>

Aligning flex items horizontally in a vertical flex container

I can't figure out for the life of me how to make this page work.
I'm trying to have the "Top" be a header, the "Bottom" be the footer, and "table" and "section" be two separate columns in between.
Although I can't figure it out. Thanks.
html {
height: 100%;
}
body {
display: flex;
height: 100%;
justify-content: flex-start;
align-content: flex-start;
flex-direction: column;
flex-wrap: wrap;
margin: 0;
}
#pageTop {
background-color: lightgrey;
padding-left: 1em;
padding-top: .5em;
flex-grow: 1;
}
#table {
background-color: blue;
width: 50%;
flex-grow: 8;
flex-shrink: 1;
}
#pageSection {
background-color: lightpink;
width: 50%;
flex-flow: 8;
flex-shrink: 1;
}
#pageBot {
flex-grow: 1;
background-color: grey;
}
<body>
<div id="pageTop">Top</div>
<nav id="table">table</nav>
<div id="pageSection">section</div>
<div id="pagebot">Bottom</div>
</body>
Like Micheal_B stated:
Wrap the #table and the #section in one container. That container becomes the second flex item in the parent flex container. Then add display: flex to the new container.
Changes
Added main#pageContent to body and wrapped it around nav#table and section#pageSection
Added display: flex, justify-content: center, and flex: 2 0 auto
Changed all flex-grow and flex-shrink to flex shorthand.
ex. flex: 0 1 auto = flex-grow: 0 flex-shrink: 1 flex-basis: auto
note. The ruleset above is default for all flex children.
Removed align-content and justify-content; and changed the value of flex-wrap from wrap to nowrap; and added overflow:hidden and width: 100% to normalize a little.
Added width: 100% to everything with the exception of #pageSection and #table.
Added height: 2em to #pageTop and #pageBot(BTW, corrected typo)
Changed all of the tags to it's semantic equivalents.
main#pageContent
Height is set up to take up the freespace that the footer and header leave by height: calc(100% - 4em). This probably overkill since it also has flex: 2 0 auto.
It is a flex container (flex: display) and a flex child (flex: 2 0 auto)
section#pageSection
overflow-x: hidden will prevent any content from busting out of the borders sideways. overflow-y:auto will accommodate any content that extends the bottom border by adding a scrollbar. I have added content (a few <p>) to demonstrate.
SNIPPET
html {
height: 100%;
width: 100%;
}
body {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
flex-wrap: nowrap;
margin: 0;
overflow: hidden;
}
#pageContent {
width: 100%;
height: calc(100% - 4em);
display: flex;
justify-content: center;
flex: 2 0 auto;
}
#pageTop {
width: 100%;
height: 2em;
background-color: violet;
padding-left: 1em;
padding-top: .5em;
flex: 0 0 auto;
}
#table {
background-color: cornflowerblue;
width: 50%;
flex: 0 0 auto;
}
#pageSection {
background-color: darksalmon;
width: 50%;
flex: 1 0 auto;
overflow-x: hidden;
overflow-y: auto;
}
#pageBot {
width: 100%;
height: 2em;
flex: 0 0 auto;
background-color: gold;
}
<body>
<header id="pageTop">Top</header>
<main id='pageContent'>
<nav id="table">table</nav>
<section id="pageSection">
<p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p>
<p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p>
<p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me? " he thought. It wasn't a dream.</p>
<p>His room, a proper human room although a little too small, lay peacefully between its four familiar walls.</p>
<p>A collection of textile samples lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted
out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. Drops</p>
</section>
</main>
<footer id="pageBot">Bottom</footer>
</body>
Add a div with flex row, as it (adjust cols width with width attribute):
html {
height: 100%;
}
body {
display: flex;
height: 100%;
justify-content: flex-start;
align-content: flex-start;
flex-direction: column;
flex-wrap: wrap;
margin: 0;
}
#pageTop {
background-color: lightgrey;
padding-left: 1em;
padding-top: .5em;
}
#mainContainer {
display: flex;
flex-direction: row;
}
#table {
background-color: blue;
width: 50%;
}
#pageSection {
background-color: lightpink;
width: 50%;
}
#pagebot {
background-color: grey;
}
<body>
<div id="pageTop">Top</div>
<div id="mainContainer">
<nav id="table">table</nav>
<div id="pageSection">section</div>
</div>
<div id="pagebot">Bottom</div>
</body>
PS: I also fixed a pagebot/pageBot variant. Be aware, CSS is case-sensitive.

CSS Flexbox - Same height when a column contains multiple parts?

I have a simple question. I have a basic flex-box layout. One column takes up 2/3 of the layout, the other takes up a third. Both of them have a purple semi-transparent header (.85) with their contents are in an opaque black box.
http://codepen.io/StuffieStephie/pen/XdoBqL
body {
background: url('http://www.amazingwallpaperz.com/wp-content/uploads/Black-and-Purple-Abstract-Cool-Backgrounds-Wallpaper.jpg') center center;
background-size: cover;
font-family: 'Open Sans';
}
#featuredSlide, #featuredSlide img {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.container {
display: -webkit-flex;
display: flex;
justify-content: space-between;
color: #fff;
}
.sect {
box-sizing: border-box;
width: 32%;
-webkit-flex: 1;
flex: 1;
margin: 30px; text-align: center;
}
.sect + .sect {
margin-left: 10px;
}
.sect.feat {width: 65%;
-webkit-flex: 2;
flex: 2;
}
.sect .cont {
background:#414141;
padding-top: 40px;
padding-bottom: 30px;
border-radius: 0 0 5px 5px;
}
.sect h2 {
background:#414141;
background-color: rgba(52,41,109,.85);
margin-bottom: 0;
text-align: center;
text-transform: uppercase;
font-size: 2em;
font-weight: 300;
padding: 30px 10px;
border-radius: 5px 5px 0 0;
}
<head><link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="container">
<div class="sect feat">
<h2> Featured Guests & Programming</h2>
<div class="cont">
<!-- SLIDE SHOW -->
<div id="featuredSlide" class="owl-carousel">
<img src="http://placehold.it/800x300/5d64a8">
</div> <!-- CLOSING SLIDE SHOW DIV TAG --></div>
</div>
<div class="sect">
<h2> News </h2>
<div class="cont">Some thrilling article</div>
</div>
</div>
<div class="clearfix"></div>
</body>
Both .sect elements are the same height. I want both .sect .cont elements to be the same height. I know I can make them look the same height by setting a background-color to .sect but that will ruin the transparency of my headers.
Any thoughts?
You can add flex-direction: column; to your .sect class, and give your .cont class a flex-grow: 1. This will make the .cont div's take up the remaining height of the .sect class.
.sect {
display: flex;
flex-direction: column;
}
.cont {
flex-grow: 1;
}
CodePen
You absolutely can do this with css only. Add the following to your .sect properties:
overflow: hidden;
position: relative;
border-radius:5px;
and add this to make the heights match:
.sect + .sect .cont::after {
background: #414141 none repeat scroll 0 0;
content: "";
height: 3000px;
left: 0;
position: absolute;
width: 100%;
}
You should also then be able to take out your border radii from the h2 and .cont as well.

Flexbox, responsive grid of square divs maintaining aspect ratio

I'm trying to create a 2x2 grid with divs. Some of the divs might contain an image, but it will probably be set as a background, with the option background-size: cover.
Here's the pen I created: http://codepen.io/qarlo/pen/vLEprq
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: auto;
max-width: 960px;
width: 80%;
}
.container__item {
align-content: center;
border: 1px solid #333;
display: flex;
flex-basis: 1;
font-size: 3em;
justify-content: center;
height: 100%;
margin-bottom: 1em;
min-height: 300px;
width: 47%;
}
<div class="container">
<div class="container__item">?</div>
<div class="container__item">?</div>
<div class="container__item">?</div>
<div class="container__item">?</div>
</div>
I'd like to force the divs to be squares and maintain the aspect ratio when resizing it. I was mistakenly hoping that this would have been straightforward with flexbox, but unless I'm missing something, I was wrong.
To maintain your items aspect ratio, a very simple method is to use CSS Viewport units
I modified your pen to see how this units work: http://codepen.io/vladbicu/pen/wMBmOb
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: auto;
max-width: 960px;
width: 80%;
}
.container__item {
align-content: center;
border: 1px solid #333;
display: flex;
flex-basis: 1;
font-size: 3em;
justify-content: center;
margin-bottom: 1em;
// maintain aspect ratio
width: 30vw;
height: 30vw;
}
Hope it helps.
Use the old "padding-bottom" trick for fixed aspect ratio. Extra divs are reqiured though:
.container {
margin: auto;
width: 80%;
max-width: 960px;
}
.container__square {
float: left;
position: relative;
padding-bottom: 50%;
width: 50%;
background: linear-gradient(45deg, #CCC, #000, #CCC);
}
.container__square__item {
position: absolute;
top: 1em;
bottom: 1em;
left: 1em;
right: 1em;
border: 1px solid #333;
background: #FFF;
}
/* clearfix */
.container::after {
content: "";
display: block;
clear: both;
}
<div class="container">
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
<div class="container__square">
<div class="container__square__item">?</div>
</div>
</div>
Guess you would have to set at least the min-height to maintain the aspect ration on re-size, if you want to go with a flex-box layout.
Here is a quick and dirty example.
function setCellsMinHeight (parentSelector, cellsMargin, aspect) {
var winWidth = window.innerWidth,
containerList = document.querySelectorAll(parentSelector),
containerArray = Array.prototype.slice.call(containerList),
childMargin = cellsMargin;
containerArray.forEach(function(elem) {
var containerWidth = elem.offsetWidth,
childCount = elem.children.length,
childWidth = (containerWidth - ((childMargin * 2) * childCount)) / childCount,
childMinHeight = (childWidth / 100) * aspect;
for (i = 0; i < childCount; i++) {
elem.children[i].style.margin = childMargin + "px";
elem.children[i].style.minHeight = childMinHeight + "px";
}
});
}
window.onresize = function(event) {
setCellsMinHeight('.container', 4, 100);
};
setCellsMinHeight('.container', 4, 100);
body {
margin: 0;
}
.container {
display: flex;
flex-flow: row wrap;
align-items: stretch;
max-width: 100%;
margin: 0 auto;
}
.content-cell {
flex: 1;
background-color: #ccc;
}
#media (min-width: 801px) {
.container {
max-width: 800px;
}
}
<div class="container">
<div class="content-cell"></div>
<div class="content-cell"></div>
</div>
<div class="container">
<div class="content-cell"></div>
<div class="content-cell"></div>
</div>
Hope it helps.
As i understand i think you want flexible boxes all the time so you can perform this action by using JavaScript.
Find the Highest height of the content
assign that highest width and height for the whole classes
and that's how you can maintain flexible boxes
or you can use external library
Css tricks
JQuery Flexbox

Resources