positioning sticky sidebar right beside a centered div - html

I'm trying to customize my blog layout by adding a sticky sidebar. I managed to get position:sticky to work as excepted, but I can't figure out how to position the blocks where I want.
I want the main block to be centered, and the sidebar right beside the main block. here's an example of what I'm aiming for: https://theme-next.js.org/ except I want the main block to be centered.
this is the layout I want
I've tried using margin-left with the sidebar, but it doesn't work well in smaller windows, as the left margin is constant and pushes the real content away in smaller windows.
this is what happens by using margin-left
(I'm not sure why the sticky dosen't work here, but it works fine on my website. All I'm trying to figure out is how to position them where I want.
.wrapper {
display: flex;
justify-content: space-between;
}
.sidebar {
width: 80px;
background-color: #FF0000;
position: webkit-stiky;
position: sticky;
align-self: flex-start;
height: 1000px;
}
.main {
width: 100px;
background-color: #CFCFCF;
margin: auto;
height: 1600px;
}
.header {
background-color: #F3FF00;
width: 150px;
margin: auto;
}
<div class="header">
<p>
this is centered header
</p>
</div>
<div class="wrapper">
<div class="sidebar">
<p> sidebar here</p>
</div>
<div class="main">
<p>
I want this block to be centered;
</p>
</div>
</div>

There's a few things you need to do here:
Set a top property for your sticky sidebar, or it won't stick
Make your main element a flex parent since we'll need to offset its child element to make it centered with your header.
Create an inner element for your main element so you can move it to the left 80px to accommodate for the sidebar width.
.wrapper {
display: flex;
position: relative;
}
.sidebar {
width: 80px;
height: 1000px;
background-color: #FF0000;
position: sticky;
/* you need a top position set for sticky */
top: 0;
}
.main {
height: 1600px;
background-color: #eeeeee;
/* This needs to be a flex parent */
display: flex;
justify-content: center;
/* This element needs to be 100% MINUS the sidebar width of 80px */
flex: 1 0 calc(100% - 80px);
}
.main-inner {
width: 100px;
position: relative;
background-color: #CFCFCF;
/* Move the inner element 80px to the left */
margin-left: -80px;
text-align: center;
}
.header {
background-color: #F3FF00;
width: 150px;
margin: 0 auto;
}
<div class="header">
<p>this is centered header</p>
</div>
<div class="wrapper">
<div class="sidebar">
<p>sidebar here</p>
</div>
<div class="main">
<div class="main-inner">
<p>I want this block to be centered;</p>
</div>
</div>
</div>
However, I believe this is what you really want:
Make the header a flex parent as well.
.wrapper {
display: flex;
position: relative;
}
.sidebar {
width: 80px;
height: 1000px;
background-color: #FF0000;
position: sticky;
/* you need a top position set for sticky */
top: 0;
}
.main {
height: 1600px;
background-color: #eeeeee;
/* This needs to be a flex parent */
display: flex;
justify-content: center;
/* This element needs to be 100% MINUS the sidebar width of 80px */
flex: 1 0 calc(100% - 80px);
}
.main-inner {
width: 100px;
position: relative;
background-color: #CFCFCF;
/* Move the inner element 80px to the left */
text-align: center;
}
.header {
display: flex;
justify-content: flex-end;
}
.header-inner {
background-color: #F3FF00;
text-align: center;
width: calc(100% - 80px);
background-color: #F3FF00;
}
<div class="header">
<div class="header-inner">
<p>this is centered header</p>
</div>
</div>
<div class="wrapper">
<div class="sidebar">
<p>sidebar here</p>
</div>
<div class="main">
<div class="main-inner">
<p>I want this block to be centered;</p>
</div>
</div>
</div>

Related

Dynamic NavBar in which the logo is always in the middle

My goal: A responsive navbar where the logo is always in the middle and an element
is always on the left. Depending on the context (page dependent), buttons can be
displayed in the right area or not.
My approach: I use a flexbox for the navbar. I have three divs in the flexbox. I have given all divs a fixed width. The middle box is also a flexbox. The div with a logo is located there. I position the logo on the right edge of the middle flexbox. The div with the logo has a fixed width (80px).
The problem: The approach works but I don't find this way very nice. Because the widths are dependent on each other. If you would change the logo and it would be wider or narrower then you would have to adjust the relative width of the middle and right box. The second problem is if the device smaller as 900px then this solution dont work.
Question: What other possibilities are there and what possibilities would resolve this "width" dependency?
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
header {
height: 80px;
display: flex;
justify-content:space-between;
}
.header-left {
width:20%;
background: green;
}
.header-middle {
width:34%;
background: gray;
display: flex;
justify-content:flex-end;
}
.header-right {
width:46%;
background: green;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;font-size:70px;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div style="width:50%; background: black;color:white; text-align:center;">Controller Div 50%</div>
</div>
</div>
You can use flex-grow: 1 on the left and right elements, the middle element will be in center naturally. In this case, you don't need to set widths on elements.
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
header {
height: 80px;
display: flex;
justify-content:space-between;
}
.header-left {
flex-grow: 1;
background: green;
}
.header-middle {
background: gray;
display: flex;
justify-content:flex-end;
}
.header-right {
flex-grow: 1;
background: green;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;font-size:70px;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div style="width:50%; background: black;color:white; text-align:center;">Controller Div 50%</div>
</div>
</div>
Since you're looking for different possibilities i'll suggest you to take the approch used by Tepken Vannkorn :
Centering brand logo in Bootstrap Navbar
Based on your comments, I would suggest the following code as a simple solution.
I have added a max-width value to your .logo CSS class and I have also moved your inline CSS from the front-end code, and created a .controller CSS class for it.
#app {
margin: 0 auto;
max-width: 900px;
width: 100%;
}
header {
height: 80px;
display: flex;
justify-content: space-between;
}
.header-left {
width: 20%;
background: green;
}
.header-middle {
width: 34%;
background: gray;
display: flex;
justify-content: flex-end;
}
.header-right {
width: 46%;
background: green;
}
.logo {
background-color: red;
width: 80px;
height: 80px;
text-align: center;
font-size: 70px;
max-width: 80px;
}
.controller {
width: 50%;
background: black;
color: white;
text-align: center;
}
<div id="app">
<small>width: 900px</small>
<header>
<div class="header-left">Burger Menu</div>
<div class="header-middle">
<div class="logo">
I
</div>
</div>
<div class="header-right">Context Buttons</div>
</header>
<div>
<div class="controller">Controller Div 50%</div>
</div>
</div>
A solution would be to use a mix of flex and position: absolute. Then you need only the left and the right container. the logo you can center with position left: left: calc(50% - calc(80px / 2));. The 80px is the width from your logo.
* {
margin: 0;
padding: 0;
}
#app {
margin: 0 auto;
max-width: 900px;
width:100%;
}
.header {
display: flex;
justify-content: space-between;
height: 80px;
background: yellow;
position: relative;
}
.header-left {
background-color: green;
width: 20%
}
.header-right {
background-color: green;
width: 44%;
}
.logo {
background-color: red;
width:80px;
height: 80px;
text-align:center;
font-size:70px;
position: absolute;
left: calc(50% - calc(80px / 2));
}
<div id="app">
<div class="header">
<div class="header-left">left</div>
<div class="logo">X</div>
<div class="header-right">right</div>
</div>
<div style="width:50%; background: black;">Controller Div 50%</div>
</div>

Fixed position sidebar within a flex container

I have a layout which uses flexbox to position a main content section and a sidebar element beside each other, with justify-content: space-between for consistent spacing within a container, however I need the sidebar on the right to also scroll down the page with the user by using position: fixed, whilst also remaining pinned to the right edge of the container.
Example pen: https://codepen.io/StyleMeLikeOneOfYourFrenchGirls/pen/BazQOLj
.container {
width: 1000px;
margin: auto;
border: 1px solid black;
}
.content {
display: flex;
justify-content: space-between;
}
.left-content {
height: 1000px;
width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 20%;
background-color: yellow;
/*position: fixed;*/
}
<div class="container">
<div class="content">
<div class="left-content">
left content
</div>
<div class="right-sidebar">
right sidebar
</div>
</div>
</div>
I understand that fixed removes the element from document flow, and thus eliminates the simplicity of the flex layout and the ability to 'contain' something within it's parent element.
I've been able to achieve something close to what I want, but it requires specific values for different viewport widths (e.g. using Bootstrap's offset classes, transform: translateX() or various combinations of margins). These methods are messy though, and don't provide a consistent solution to keeping the sidebar aligned with the edge of the parent container.
Is there a simpler/more elegant solution to this problem?
You can use position: sticky;. It respects the flex and has a fixed purpose.
DEMO:
.container {
width: 1000px;
margin: auto;
border: 1px solid black;
}
.content {
display: flex;
justify-content: space-between;
}
.left-content {
height: 1000px;
width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 20%;
background-color: yellow;
position: -webkit-sticky;
position: sticky;
top: 0;
}
<div class="container">
<div class="content">
<div class="left-content">
left content
</div>
<div class="right-sidebar">
right sidebar
</div>
</div>
</div>
Please have a look...
body {
margin: 0;
}
.container {
width: 1000px;
display: block;
margin: 0 auto;
}
.content {
background: #999;
height: 100vh;
overflow: auto;
display: flex;
}
.leftContent {
display: flex;
width: calc( 100% - 300px );
}
.rightSidebar {
position: absolute;
right: calc(50% - 500px);
background: #666;
height: 100vh;
width: 300px;
overflow: auto;
}
<div class="container">
<div class="content">
<div class="leftContent">
a a a a a a a a a a a a a a a a a. a a a a. a a a a a a a a. a a a a a a a aa. a a a a a a a a a a a a a a a a a a a. a a a a. a a a a a a a a. a a a a a a a aa. a aa<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>
</div>
<div class="rightSidebar">
b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>
</div>
</div>
</div>
Here is a try with minimum impact on your code.
The setup you have limits a bit the options you have, but I think below Pen would be a nice workaround.
.left-content {
height: 1000px;
width: 100%;
max-width: 70%;
background-color: red;
}
.right-sidebar {
height: 200px;
width: 100%;
max-width: 15%;
background-color: yellow;
position: fixed;
right: 20%;
}
CodePen
Sidebar on the right hand side scrolls down the page with the user by using position: fixed, whilst also remaining pinned to the right edge of the container.

Image overflows fixed-height flex container

I'm using a fixed-height flex container to do the layout. In the container, there are three components: header, content, footer. I want to force the content to use the rest of the height (i.e. content height = fixed-height minus header and footer). In my content, it will include an image and some texts.
However, the image always overflows a fixed-height flex container even providing max-height: 100% to constrain the height, but I want to put header, content, and footer into a fixed flex container.
Does anyone know how to fix it?
code: https://codepen.io/mrchung402/pen/wvGPJxz
<div class="container">
<div class="header">
header
</div>
<div class="content">
<div class="my-img">
<img src="http://via.placeholder.com/274x295">
</div>
<div class="my-text">
my-text
</div>
</div>
<div class="footer">
footer
</div>
</div>
.container {
border: solid 1px red;
display: flex;
max-width: 500px;
height: 200px;
flex-direction: column;
}
.header {
flex: 0 0 auto;
background: #A7E8D3;
}
.content {
display: flex;
flex-direction: column;
}
.footer {
flex: 0 0 auto;
background: #D7E8D4;
}
.my-img {
max-height: 100%;
height: auto;
max-width: 100%;
}
img {
max-height: inherit;
height: inherit;
}
.my-text {
background: #C7A8D4;
}
Instead of styling .my-img you should style .my-img img
.my-img img{
height: 100%;
width: 100%;
}

Position title over image

I need to create something like the image below, without using any frameworks like bootstrap. Basically, I need the image to not be full width, but to take say 80% of the screen, and the title of the webpage to be above that image. At the moment all of my content is flowing all around the page.
It should also remain the same when I make the screen smaller.
I don't know why something simple is just not working for me...
.container {
width: 100%;
}
}
#main {
background: red;
width: 80%;
margin: 0 auto;
}
img {
max-width: 100%;
width: 80%;
float: right;
display: block;
}
<div id='main'>
<div class='container'>
<!--Image-->
<div id='img-div'>
<img id='image' src='https://www.projectarm.com/wp-content/uploads/2018/01/Frida-Kahlo-Vogue-1939-New-York-foto-di-Nickolas-Murray-2.jpg' />
<div id='img-caption'>This is a caption for the image</div>
</img>
</div>
<!--Title-->
<div id='pagetitle'>
<h1 id='title'>Frida Kahlo</h1>
<span id='tagline'>A short Tribute</span>
</div>
<!--End Title-->
</div>
<div id='tribute-info'>
This is my main information about the person
This is a link for more information
</div>
I would use flex for your container, so you can swap the order and it is a more up to date way to position things than floating, then inline block for your tag lines
Please note your image tag is invalid - img tags are self closing
.container {
width: 100%;
display: flex; /* make the container flex */
flex-direction: row; /* align the children in a row */
}
#img-div {
max-width: 85%; /* 85% width */
flex-basis: 85%;
order: 2; /* put this div 2nd */
}
#image {
display: block;
width: 100%; /* make div stretch size of div */
}
#pagetitle {
box-sizing: border-box; /* make this div 15% width with a bit of padding */
padding: 20px;
max-width: 15%;
flex-basis: 15%;
order: 1; /* put this div 1st */
display: flex; /* make this flex for vertical aligning and align children in a column */
flex-direction: column;
justify-content: center; /* vcertical align center (only works with flex) */
overflow: visible; /* show overflow */
position: relative; /* make overflow appear on top of image */
z-index: 2;
}
#title {
font-size: 20px;
font-weight: normal;
}
.tag-holder {
position: relative;
}
.tagline {
display: inline-block; /* make inline block so you can add white background */
white-space: nowrap;
font-size: 30px;
font-weight: bold;
text-transform: uppercase;
background: white;
padding:0.1em 0.5em;
}
<div id='main'>
<div class='container'>
<!--Image-->
<div id='img-div'>
<img id='image' src='https://www.projectarm.com/wp-content/uploads/2018/01/Frida-Kahlo-Vogue-1939-New-York-foto-di-Nickolas-Murray-2.jpg' />
</div>
<!--Title-->
<div id='pagetitle'>
<h1 id='title'>Emilia<br>Cole</h1>
<div class="tag-holder">
<span class='tagline'>Twist</span>
<span class='tagline'>in my</span>
<span class='tagline'>reality</span>
</div>
</div>
<!--End Title-->
</div>
<div id='tribute-info'>
This is my main information about the person
This is a link for more information
</div>
Without flex:
.container {
width: 100%;
position: relative;
}
.container:after {
content: '';
display: block;
height: 0;
clear: both;
overflow: hidden;
}
#img-div {
width: 85%;
/* 85% width */
float: right;
}
#image {
display: block;
width: 100%;
/* make div stretch size of div */
}
#pagetitle {
position:absolute; /* this is for 100% height */
top:0; bottom:0;
left:0;
right:15%;
overflow: visible;
z-index: 2;
}
.center { /* center text vertically */
position:absolute;
top:50%;
left:20px;
transform:translateY(-50%);
}
#title {
font-size: 20px;
font-weight: normal;
margin-top:0;
}
.tag-holder {
position: relative;
}
.tagline {
display: inline-block;
/* make inline block so you can add white background */
white-space: nowrap;
font-size: 30px;
font-weight: bold;
text-transform: uppercase;
background: white;
padding: 0.1em 0.5em;
}
<div id='main'>
<div class='container'>
<!--Image-->
<div id='img-div'>
<img id='image' src='https://www.projectarm.com/wp-content/uploads/2018/01/Frida-Kahlo-Vogue-1939-New-York-foto-di-Nickolas-Murray-2.jpg' />
</div>
<!--Title-->
<div id='pagetitle'>
<div class="center">
<h1 id='title'>Emilia<br>Cole</h1>
<div class="tag-holder">
<span class='tagline'>Twist</span><br>
<span class='tagline'>in my</span><br>
<span class='tagline'>reality</span>
</div>
</div>
</div>
<!--End Title-->
</div>
<div id='tribute-info'>
This is my main information about the person
This is a link for more information
</div>
Try this image caption is placed on top
.container {
width: 100%;
}
}
#main {
background: red;
width: 80%;
margin: 0 auto;
}
img {
max-width: 100%;
width: 80%;
float: right;
display: block;
}
#img-caption{
position: absolute;
left: 50%;
margin-left: -50px; /* margin is -0.5 * dimension */
}
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tribute Page</title>
</head>
<body>
<div id='main'>
<div class = 'container'>
<!--Image-->
<div id='img-div'>
<img id='image' src='https://www.projectarm.com/wp-content/uploads/2018/01/Frida-Kahlo-Vogue-1939-New-York-foto-di-Nickolas-Murray-2.jpg'/>
<div id='img-caption' class='alert alert-info'>This is a caption for the image</div>
</div>
<!--Title-->
<div id='pagetitle'>
<h1 id='title'>Frida Kahlo</h1>
<span id ='tagline'>A short Tribute</span>
</div>
<!--End Title-->
</div>
<div id ='tribute-info'>
This is my main information about the person
This is a link for more information
</div>
</div>
</body>
</html>
I was able to solve it simply by giving my container element a relative positioning, and my title #pagetitle element an absolute positioning, and then positioning the title top: 30px and left 30px RELATIVE to my container element. In this way, my title was positioned relative to the container, and not to the page - which would otherwise be the case had I not given the relative positioning to the container of the title.
.container {
height: 90vh;
min-height: 410px;
margin-top: 40px;
position: relative;
}
#pagetitle {
font-size: 2em;
text-transform: uppercase;
letter-spacing: 0.3em;
position: absolute;
top: 30px;
left: 30px;
}
I also gave a height to my container to make sure the content won't flow around it.
This can be easily done with CSS Grid, which is a more modern technology as well, but I preferred to stick to the traditional positioning to learn and fully understand them before skipping steps and using the easier grid system.
Whole pen and result can be seen here: https://codepen.io/commiesar/pen/GBMLza?editors=1100

adding inline-block divs moves parent to the bottom of the screen

I have 2 divs (.showcase, .highlight) nested inside an element with position: relative:
I would like to have a margin on the left of the .contentContainer for the navigation menu (23.79%). Then I would like 2 divs inside the contentContainer div that extend the whole height of the screen, regardless of their content. Then I would like to add content inside those two divs.
<div id="App">
<div data-reactroot="">
<div class="navbarContainer">
</div>
<div class="contentContainer">
<div class="showcase">
<div class="thumb"></div>
<div class="thumb"></div>
<div class="thumb"></div>
<div class="thumb"></div>
</div>
<div class="highlight"></div>
</div>
</div>
</div>
Now when I add more divs into my showcase div, the .showcase div gets moved to the bottom of the screen (so only the 100px of the .thumb divs are visible.). I can't figure out what I am doing wrong.
Stylesheet:
#App {
background-color: #fff;
color: $fontC2;
font-family: 'Roboto';
min-height: 100vh;
min-width: 320px;
position: relative;
}
.contentContainer {
margin-left: 23.79%;
width: 76.21%;
height: 100vh;
.showcase {
width: 61%;
height: 100vh;
display: inline-block;
background-color: red;
top: 0;
.thumb {
width: 20%;
height: 100px;
background-color: $primaryC3;
display: inline-block;
}
}
.highlight {
width: 39%;
background-color: $primaryC2;
height: 100vh;
display: inline-block;
}
}
Fiddle here:
https://jsfiddle.net/2tz9940v/