Flexbox layout, push content when opening sidebar? - flexbox

So here is a picture reference for this question:
What I would like to do is, using flexbox layout 3 columns (left side bar, center content, *optional right side bar). Basically, you have the 3 columns but only show the left side bar and content columns normally. Then, when the user clicks the menu button, have the right side bar content come into view (as shown by the red part in the drawing).
I figured the parent container to start would look something like:
body {
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: stretch;
}
What else would be needed (especially for the right side push in sidebar) to get this working with flexbox?

You are so close.
In order to make the content column grow when the right sidebar is hidden, you need a positive flex-grow on it.
And in order to make the body cover all the screen, remove its margin and use height: 100% on both html and body.
Here is a working example:
document.querySelector('button').addEventListener('click', function() {
document.getElementById('right').classList.toggle('hidden');
});
html, body {
margin: 0;
height: 100%;
}
body {
display: flex;
flex-flow: row nowrap;
}
.sidebar {
width: 25%;
background: #777;
}
#content {
flex-grow: 1;
background: #000;
}
.hidden {
display: none;
}
<div id="left" class="sidebar"></div>
<div id="content">
<button type="button">Toggle sidebar</button>
</div>
<div id="right" class="sidebar hidden"></div>

Related

How to get text in a CSS grid nested in a flexbox to wrap first?

TL;DR: Here's a CodePen.
I have a UI with an image and a grid of text with long lines which looks like this:
I'm using CSS Flexbox with two elements: the image and the text. And then to lay out the text, I'm using CSS Grid. Now, when I view this on a narrow screen for mobile, it correctly wraps everything and stacks the two elements:
But on desktop, with a slightly narrower div, the flex box wraps before the grid text like this:
How can I get the text to wrap while leaving the flex box alone in this case? I fear I may need to use some media queries, but I'm not even sure if I'm using the right CSS components for this.
Here's the code:
index.html:
<div class="media-callout">
<div class="media-thumb">
<img height="170" width="120">
</div>
<div class="media-callout-grid">
<div class="media-callout-key">Authors</div>
<div>Babalola, J & Ogunkola, Babalola</div>
<div class="media-callout-key">Year</div>
<div>2013</div>
<div class="media-callout-key">Title</div>
<div class="media-callout-value">Scientific Literacy: Conceptual Overview, Importance and Strategies for Improvement</div>
<div class="media-callout-key">Journal</div>
<div><em>Journal of Educational and Social Research</em></div>
<div class="media-callout-key">Location</div>
<div>vol. 3, no. 1, pp. 265–274</div>
<div class="media-callout-key">DOI</div>
<div>10.5901/jesr.2013.v3n1p265</div>
</div>
</div>
style.css:
.media-callout {
display: flex;
flex-wrap: wrap;
justify-content: center;
row-gap: 20px;
column-gap: 10px;
padding: 1em;
max-width: max-content;
}
.media-thumb img {
float: left;
height: 175px;
width: auto;
}
.media-callout-grid {
display: grid;
font-size: 12pt;
grid-template-columns: 6em 1fr;
align-content: center;
gap: 0 15px;
}
.media-callout-key {
text-align: right;
font-weight: bold;
}
.media-callout-value {
word-break: break-word;
word-wrap: break-all;
}
A media query does indeed resolve this:
#media screen and (min-width: 600px) {
.media-callout {
flex-wrap: nowrap;
}
}
The query must come AFTER the .media-callout block. I also had to use this approach to prevent the image from being squashed.

Dropdown Menu Breaks Sticky Footer

I have a footer with dynamic content & height, so i'm using the display:table version of sticky footer. The problem is I have a menu with an absolute positioned drop-down that extends past the footer if the page is too small, menu too big, etc. This creates a gap below the footer. Check out the fiddle for an example. Thanks.
http://jsfiddle.net/wmTn9/
Here's the css, although its easier to see in the fiddle.
html, body {
height: 100%;
margin: 0;
}
.wrapper {
display: table;
height: 100%;
width: 100%;
background: yellow;
}
.content {
display: table-row;
height: 100%;
background: turquoise;
position:relative;
}
.menu {
position:absolute;
left:0;
width:50%;
background:yellow;
overflow:hidden;
max-height:20px;
}
.menu:hover {
max-height:1000px;
}
.menu li {
height:800px
}
.footer {
display: table-row;
background: lightgray;
}
.footer:hover h3 {
height:300px;
}
In your CSS, take position:absolute; out of the menu class and the footer will move down to accommodate the long menu. If you want the footer to remain at the bottom of the browser window, add the following into your footer class...
width:100%;
position:fixed;
bottom:0;
position:absolute; takes the element out of the document flow. The element is then positioned relative to its first positioned (not static) ancestor element. Taking it out of the menu class puts the menu back into the document flow and stops the menu overlapping the footer.
Amended Fiddle with footer stuck to the bottom of the browser window

How to align on the right an inline-block element?

As you can see in the following Fiddle: http://jsfiddle.net/EvWc4/3/, I'm currently searching a way to align the second link (link-alt) to the right side of its parent (p).
Why not using float or position:absolute you'll say, well the main reason is that I like the fact that the links' display (inline-block) property allow them to be verticaly aligned in a naturally kind of way.
By using float or position:absolute; I'll be forced to calculate and put some extra margin-top or top value to vertically aligned the links.
Here is the code but better see the Fiddle http://jsfiddle.net/EvWc4/3/ :
<p>
link
link alt
</p>
p {
padding: 20px;
background: #eee;
}
.link {
display: inline-block;
padding: 10px;
background: #ddd;
}
.link-alt { padding: 20px; }
To do this with CSS3 you can use the flex box model
HTML:
<div class="content">
<div class="box box1"><a>Link 1</a></div>
<div class="box box2"></div>
<div class="box box3"><a>Link 2</a></div>
</div>
CSS:
.content {
display: box;
box-orient: horizontal;
box-pack: center;
box-align: center;
}
.box2 {
box-flex: 1;
}
(needs vendor prefixes)
http://jsfiddle.net/EvWc4/18/
CSS3 flex and grid items are supposed to address these issues, but standard support remains spotty as of 2013.
Back to the real world. I don't think it is possible to do this purely in CSS2.1 (IE8+) without pixel hacks. The thing is, text alignment is controlled by the parent element, and since the two anchors share their parent, they either both align to the left or to the right. And justify doesn't work on the last line.
If you can suffer a little additional HTML, there are two approaches:
1) Add another inline that is guaranteed to wrap the line, and then try to hide the empty line. This allows you to use text-align justify on the parent.
<p>
link
link alt
<span class="boom"></span>
</p>
<style type="text/css">
p {
padding: 20px;
background: #eee;
text-align: justify
}
.link {
display: inline-block;
padding: 10px;
background: #ddd;
}
.link-alt {
padding: 20px;
}
span {
display: inline-block;
height: 0;
width: 100%
}
</style>
Pros: works on any number of inline blocks, not just two. Only a little extra HTML required.
Cons: takes extra effort to hide the last (empty) line of text (setting the inline block inside of it to 0 height won't help you), and you're going to have to fiddle with margins or something else to make it really work. Further discussion: How do I *really* justify a horizontal menu in HTML+CSS?
2) Add another layer of inline blocks on top of your anchor tags and size them to 50%. Then you can apply separate text-align to get the final layout you requested. It is important that no whitespace is allowed between two inline blocks sized to 50%, or you'll wrap the line.
<p>
<span class="left">
link
</span><span class="right">
link alt
</span>
</p>
<style type="text/css">
p {
padding: 20px;
background: #eee;
}
.link {
display: inline-block;
padding: 10px;
background: #ddd;
}
.link-alt {
padding: 20px;
}
span {
display: inline-block;
width: 50%
}
.left {
text-align: left
}
.right {
text-align: right
}
</style>
Pros: produces the exact layout you requested without polluting the outer box model.
Cons: only works for two inline blocks (you can try to extend it, but it quickly gets really complicated). Relies on having no extra whitespace, which could jeopardize your nicely formatted markup.
You could set the position to absolute and use right: 0
.wrapper {
position: relative;
}
.right {
position: absolute;
right: 0;
}
http://jsfiddle.net/EvWc4/13/
I believe this accomplishes what you're looking for:
.link-alt {
position: absolute;
right: 0; top: 0; bottom: 0;
margin: auto;
max-height: 1em;
}
You can use position: absolute and right: 0 to obtain the right alignment. To keep the vertical centering, you can use top: 0; bottom: 0; margin: auto;. Of course, you'll also need to set a height on the element, or it will stretch to the full height of its parent.
Here's a jfiddle: http://jsfiddle.net/pHppA/
I've updated Pethas example, so it can be done in pure CSS2. It doesn't work in IE7, as it doesn't support display: table-cell; which I use.
http://jsfiddle.net/EvWc4/133/
The attribute float has no bearing on the element's vertical positioning.
p{padding:20px;background:#eee;overflow:auto;}
.link-alt{padding:20px; float:right}
should accomplish what you're looking for. Setting the overflow of the parent to something besides it's default (visible) will force it to treat floating children like normal elements.
Reference article
I haven't tested this at all outside of Chrome, so it might suck for IE.
This simple (and limited) solution leverages text-align: right and width: 50% on the aligned children, and white-space: nowrap on the parent to achieve the desired result.
Example: http://jsfiddle.net/erikjung/ejcJZ/
.vertically-centered-module {
white-space: nowrap;
}
.vertically-centered-module > * {
display: inline-block;
vertical-align: middle;
width: 50%;
}
.vertically-centered-module > :last-child {
text-align: right;
}

CSS: issue with background color

I want to make the header and footer backgrounds to be repeated on x. So it takes all the width size of any page resolution.
This is how I want it to look like:
An this how is being displayed:
I'm using the 960 gs, every div is limited to 960px. Is there a way to expand the color of the div through x?
See the project here:
http://gabrielmeono.com/yonature/
yes there is
you have to split the page into 3 parts: header, body, footer
what we're gonna do is create divs with a little bit of CSS. we will have a div that goes all the way to the sides of the website, and a div which is centered.
i'll show you how to do it for the header, and you make the same thing for body/footer:
<html>
<head>
<style type="text/css">
html{}
body { margin: 0px; width: 100%; }
#headerCenter { float: left; width: 100%; text-align: center; color: #00AA00; height: 120px; }
#headerContainer { margin: 0 auto; width: 960px; }
#header { width: 100%; float: left; height: 120px; }
</style>
</head>
<body>
<div id="headerCenter">
<div id="headerContainer">
<div id="header">HEADER</div>
</div>
</div>
.. same for body/footer....
</body>
</html>
so the trick is:
a div (#headerCenter) which goes all the way across the page. we will define height for it, paint it's background, and set 'text-align: center;'
inside we put a div with 'margin: 0 auto;' and the desired width. NO FLOAT on this div! this will create a div with height 0, placed in the center of the parent div.
inside we put the header. we can set float left etc... width can be 100% (or 960px)
repeat this for body and for footer
another method btw is using HTML tables, which i don't like to use for layouts.
if you have any trouble setting this up, let me know and i'll do the layout for you

No scrollbar for DIV wider than browser

I'm doing some tests on a website using Wordpress as a CMS. In the example below the top left of the page has an "S" graphic outside of the main content area, clipped accordingly depending on the browser width. I would like to do something similar with an "L" graphic to the right in the footer.
The page width is set to 960px, and I've made the footer container DIV 1088px so that the "L" appears outside the content area. The trouble is this makes a scrollbar appear when it exceeds the current width of the browser.
I've tried overflow:hidden on the footer container DIV but this doesn't seem to work. I've also tried overflow:hidden on the BODY element and this works ok in IE, but not in other browsers.
Example: http://unclemort.com/wp/
I really hope there is away to do this, any help gratefully received.
I was trying to figure this out myself today and stumbled upon the answer.
What you need is a surrounding element around everything that has this:
#wrapper {
min-width: 600px; //whatever width you want
overflow-x: hidden;
}
Your main content should have that same width, and the things that need to jut out should have a negative margin.
Here's a complete example:
HTML:
<div id="outer">
<div id="container">
<div class="row">
<div class="inner">Hello World</div>
</div>
</div>
</div>
CSS:
#outer {
min-width: 300px;
overflow-x: hidden;
}
#container {
width: 300px;
margin: 0px auto;
background: gray;
height: 500px;
}
.row {
width: 350px;
background: blue;
margin-left: -25px;
}
.inner {
background: yellow;
margin-left: 25px;
width: 300px;
height: 100px;
}
#media screen and (min-width: 301px) {
body {
//overflow-x: hidden;
}
}
jsfiddle:
http://jsfiddle.net/aaronjensen/9szhN/
Try in style.css, line 65, adding:
#footer-container {
border: none;
overflow: hidden;
}
Explanation:
#footer-container #footer {
background: #f5e8f7 url('images/slobraico-footer-pink-full.gif') no-repeat top left;
width: 1088px;
height: 217px;
overflow: hidden;
}
The scrollbar you're hiding is effectively not there.
The scrollbar you're seing is another one.
The problem is that the footer is 1088px wide, and that's causing a scrollbar to appear.
As long as the footer has fixed width and it's parent doesn't have overflow: hidden, you'll get a scroll if there's not enough width for the footer to fit.
Same goes for any other container.

Resources