This question already has answers here:
Is it possible for flex items to align tightly to the items above them?
(5 answers)
Closed 4 years ago.
I have 3 div elements which I want to put in 2-columns. One of them I want to fill in the first column vertically and the others to fill the next column in 2
separate rows. (Run code snippet to see the sections)
.news-feed {
display: flex;
flex-flow: row wrap;
}
.image {
flex-direction: column;
height: 20px;
}
.title_date {
flex-direction: column;
}
.job-description {
flex-direction: column;
}
<section class="news-feed">
<section class="image">
<img src= 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRlUiyrmhTXFppqk4aYzqTOU9nimCQsYibukwAV8rstsDkAVQT-mA'/>
</section>
<section class="title_date">
<p class="date">27 Dec 1997</p>
<h3 class="title">Urgent Job offer</h3>
</section>
<section class="job_description">
<p class="job_info">This is a job for speacial people like you. Long text bla bla bla. The main issue is that I cannot put the 'title_date' and 'job_description' section in a single div because I want to put the 'title_date' at top of 'image' section when the device is mobile. Any workaround idea is highly appreciated. Thanks</p>
<p class="tags">Jobs, HighPay, Carrer</p>
</section>
</section>
The main issue is that I cannot put the 'title_date' and 'job_description' section in a single div because I want to put the 'title_date' at top of 'image' section when the device is mobile. Any workaround idea is highly appreciated. Thanks
This is easily achieved if you just use grid not flex in your css files. Then you won't need any JavaScript. Just change your CSS code like this:
.news-feed {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 50% 50%;
grid-template-areas:
"image title_date"
"image job_description"
}
.image {
grid-area: image;
}
.title_date {
grid-area: title_date;
}
.job-description {
grid-area: job_description;
}
#media screen and (max-width: 425px) {
.news-feed {
grid-template-columns: 100%;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
"title_date"
"image"
"job_description"
}
}
This will position image on the left in desktop mode and in the middle on the mobile version. You can of course change the columns and rows height and width as you want.
wrap "title_date" and "job_description" in one section and give them flex-direction: column; and inside that wrapper div give flex-direction: row; css to this two div "title_date" and "job_description"
I had to go javascript way to resolve this.
For this, I look into the "window.innerheight" property and according to it, I either wrap the "title_date" and "job_description" inside a new section (for normal display) or separate them and give them required flexbox ordering (for mobile display).
Related
This question already has answers here:
How can I horizontally center an element?
(133 answers)
Closed 1 year ago.
I bet this question was asked a hundred times before but i was unable to find a solution for my exact problem. I have 4 Div boxes and they have a max width of 50% and a min width of 400px, so if the site is smaller (eg. on a phone), the boxes align below each other. Now i want to center the boxes if they are below each other (it looks fine while they are side by side). I tried to use
display: table; margin: 0 auto;
but it doesnt work. Another thing I tried was to place everything inside of another div and give them the parameters above and in addition i tried to play with the width of this one (max-content, min-content, auto, fit-content) but it didn't work either. Does anyone know an easy workaround?
Here a short version of my problem:
.format {
width: 50%;
float: left;
height: auto;
min-width: 500px;
background-color: lightblue;
display: table;
margin: 0 auto;
}
<div class="format">
<p>Landestrainer</p>
</div>
<div class="format">
<p>U17</p>
</div>
<div class="format">
<p>U15</p>
</div>
<div class="format">
<p>Sonstige</p>
</div>
sorry for my partly bad english. Hopefully, it was not that bad :)
I would recommend using display: flex instead to center them.
So you would need to put all 4 divs inside a parent div and apply the css below:
.parent-div {
display: flex;
flex-direction: column;
align-items: center;
}
New Edit based on the screenshot given
My approach for this problem would be something like this:
Make use of display: flex and #media query
.parent-div {
// This will divide the page into 2 columns cause of sub-parents
display: flex;
align-item: center;
}
.sub-parent{
display: flex;
align-items: center;
flex-direction: column;
}
// #media query means that if the screen becomes smaller than 768px (specified below), then apply the CSS queries which in this case apply flex-direction: column to the "parent-div"
#media screen and (max-width: 768px) {
.parent-div {
flex-direction: column;
}
}
<div class="parent-div">
<div class="sub-parent">
<div class="format">
<p>Landestrainer</p>
</div>
<div class="format">
<p>U17</p>
</div>
</div>
<div class="sub-parent">
<div class="format">
<p>U15</p>
</div>
<div class="format">
<p>Sonstige</p>
</div>
</div>
</div>
Here's the link to CSS display: flex guide: Display Flex Guide
I am building a list of services for my website using CSS Grid. One of the rows in that overall website grid is broken into two CSS Grid columns.
In the first column of the first row, there is a description of a service. In the second column, there is an image that represents the service.
With each row, the description and image alternate, so on the second row, first column, there is an image, and in the second column, there is a description. Check out the attached image to see what I have working so far (note: I re-sized images to make it easier to take a screenshot).
The mobile version of the CSS Grid is a single column. When I display the same content in the mobile version, the layout no longer works. Since my layout is determined by the HTML content (probably a bad thing, I know), the titles will not always show up above the image, which is what I want. See attached to see the issue.
I believe the answer to solving this problem lies in using flex-direction: row-reverse; however, it is quite hard to come across some good examples (maybe I am just searching the wrong way). The best Codepen I could find does what I want using flex-direction, but it does not nicely place the description in one CSS Grid box and the image in another CSS Grid box, so when resizing the browser, the images overlap the text.. that is probably due to my lack of knowledge using Flexbox (still learning).
Could you help me figure out how to properly create an alternating 2-column list of items that also displays the text and image properly when in a 1-column list?
I would prefer to stay within the CSS Grid/Flexbox/no script world, but I am happy to entertain other ideas.
Thank you very much for any help you can provide!
HTML
<!-- Services area -->
<div class="services-area">
<div class="services-text">
<h3>This is service 1</h3>
</div>
<div class="services-div">
<img class="services-image" src="images/home/home-agile-transformation.png" alt="Agile transformation image.">
</div>
<div class="services-div">
<img class="services-image" src="images/home/home-agile-coaching.png" alt="Agile transformation image.">
</div>
<div class="services-text">
<h3>This is service 2</h3>
</div>
<div class="services-text">
<h3>This is service 3</h3>
</div>
<div class="services-div">
<img class="services-image" src="images/home/home-agile-sw-implementation.png" alt="Agile transformation image.">
</div>
</div>
CSS
// layout for services
// display a stacked grid <767 pixels
.services-area {
grid-area: svcs;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
#if $debug { background-color: $debugServicesArea; }
}
// display a 2-column grid >768
#include for-size(full-size) {
.services-area {
grid-area: svcs;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
margin-left: $gridMarginLeft;
margin-right: $gridMarginRight;
#if $debug { background-color: $debugServicesArea; }
}
}
.services-text {
display: grid;
align-items: center;
justify-content: center;
}
.services-image {
max-width: 100%;
height: auto;
}
For accessibility concerns and better SEO keep the markup in the logical order (title, image).
On mobile, you do not need a grid at all, use display:block for the container. Use grid-auto-flow: row dense to fill the grid as densely as possible following the row order. This ensure no grid cell will be empty.
Then alternate the title elements by specifying the column they need to start from. You can use the :nth-child() sibling selector to pick the titles, starting from the 3rd and then every 4 (4n - 1 means 4 * 0 - 1 = -1 (invalid sibling, skipping); 4 * 1 - 1 = 3; 4 * 2 - 1 = 7; ...).
/* display a stacked grid <767 pixels */
.services-area {
display: block;
}
/* display a 2-column grid >768 */
#media (min-width: 768px) {
.services-area {
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
justify-content: center;
grid-auto-flow: row dense;
}
}
.services-area > :nth-child(4n - 1) {
grid-column-start: 2;
}
.services-image {
max-width: 100%;
height: auto;
}
This helped me:
For example, if you want to reverse the columns on screen lower than 1200px, then in your parent div, use this instead
#media (max-width:1200px) {
.services-area {
display: flex;
flex-flow: column-reverse;
}
}
First im sorry for the sloppy Css im still new to it.
?Im trying to follow this designBut i can't figure a way to make the text align vertically without it leaving the grid header or disappearing.Any tips?
Thnx in advance.
body {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"first-section"
"second-section"
"footer";
}
header {
grid-area: header;
display: grid;
grid-template-columns: repeat(2,1fr);
grid-template-rows: auto;
}
#something{
color: red;
transform: rotate(-90deg);
}
<header>
<div id="something">
<h1>Someting</h1>
<h2>NAME GOES HERE</h2>
</div>
<div id="picture">
</div>
</header>
Instead of rotating it buy -90deg, use
#something {
color:red;
writing-mode: vertical-rl;
}
Try inspecting the #something div. Notice how it is rotated, but the grid doesn't stretch to fill it?
This is because the browser works out how things look in three separate steps:
Layout, Paint and Composite.
When you use a css transform, the browser only redoes the composite step, the layout doesn't change.
A very common element containing an image, title and text is
<div class="mediaelement">
<img src="http://placekitten.com/g/500/500" />
<h1>The title. Unknown length.</h1>
<p>And the description. Which could also span multiple lines.</p>
</div>
Now display: flex appears to be a very flexible way to center and display items. E.g with the order property I could move the title before the image without touching dom.
But is it possible to align both the h1 and p vertically to the image without putting the into another container? Using only css?
Like this: http://imgur.com/draDl2q
If i put them into a container, I cannot move the h1 before the image with the flex order value.
Yes, it is....with one proviso. You need to know the height of the parent element.
Basically, you need column layout with wrapping. In order for the parent to know when to wrap you must have a limited height...or it just won't wrap.
.mediaelement {
display: inline-flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
justify-content: center;
}
<div class="mediaelement">
<img src="http://placekitten.com/g/200/200" />
<h1>The title. Unknown length.</h1>
<p>And the description. Which could also span multiple lines.</p>
</div>
Once display:contents gains support this kind of fiddling about will become unnecessary as it will be possible to wrap and unwrap elements from their containers as required.
Here's Paulie_D's answer expanded to show the smaller issue with the widths of h1 and p. But this is already good enough solution for some cases.
.mediaelement {
display: inline-flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
justify-content: center;
width: 600px;
}
<div class="mediaelement">
<img src="http://placekitten.com/g/200/200" style="
padding-right: 10px;
">
<h1 style="
width: calc(100% - 210px);
margin: 0;
">The title. Unknown length. Could be 2 lines</h1>
<p style="
width: calc(100% - 210px);
margin: 0;
">And the description. Which could also span multiple lines.And the description. Which could also span multiple lines.</p>
</div>
Answering my own question :)
With CSS grid, this is easier to solve.
https://codepen.io/Jaska/pen/VQGqWK
.mediaelement {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 1rem;
}
img {
grid-row: 1 / 5;
}
h1 {
grid-row: 2
}
p {
grid-row: 3;
}
So the img fills all the rows 1-4 so the h1 and p have to go to the second column. And I added h1 to start from row 2 and p to start from row 3 so there remains 2 equal height rows above and under the content.
I need to create a horizontal layout where one block takes all available space and the other ones shrink to fit their content.
For example:
<div class="grid">
<div class="expand">Long text label</div>
<div class="shrink">Button</div>
</div>
A more complex example with two rows (an actual grid):
<div class="grid">
<div class="row">
<div class="shrink">...</div>
<div class="expand">...</div>
<div class="shrink">...</div>
<div class="shrink">...</div>
</div>
<div class="row">
<div class="shrink">...</div>
<div class="expand">...</div>
<div class="shrink">...</div>
<div class="shrink">...</div>
</div>
</div>
My requirements:
The large block should fill all available space even if short
The small blocks should fit their content
The large block (usually a text label) may be a single word larger that the available space, so it should be truncated in this case
The large block should not wrap if multi-word
The small blocks should not wrap (though in the case of multiple buttons or icons, this can be solved by making one block per component)
Support multiple rows (i.e. columns should be aligned)
I am targeting Android and iOS smartphones.
I have tried to adapt the code from this answer but I could not make it work for multiple rows. Also, the source code must be out of order, which is confusing (though not blocking for my use case). Here's a jsfiddle: http://jsfiddle.net/k3W8L/
You need to use grid-template-column and set the size of column you want to shrink-to-fit as auto, and specify the size of at least one other column using the fr unit.
Example:
To recreate the sidebar-content layout, where the sidebar is collapsible,
-------------------------------
| Sidebar | Content |
-------------------------------
you can create the grid as:
.grid {
display: grid;
...
grid-template-columns: auto minmax(0, 1fr); // see note below
grid-template-areas: "sidebar content";
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
See the codepen here for a demo & code: https://codepen.io/khs/pen/vegPBL
You can click on the navbar to see auto-sizing in action.
Note: One thing I've learnt since writing this answer is that in most cases, and especially in a fixed-height/fixed-width layout, you should use minmax(0, 1fr) instead of 1fr. The reason is that 1fr is actually a shorthand for minmax(auto, 1fr). This breaks when used for fixed layouts with longer content. See this question for more details: Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
Hence I've updated my answer to reflect the fact. The minmax might be a little verbose, but it's almost always what you want for this kind of layout.
Context: I bumped into this question recently while learning to use grid in my app. With some help from ilyaigpetrov's answer, I was able to get a shrink-to-fit column sizing to work. Their answer doesn't give much explanation though, so I thought I'd add this:
I found the answer to my own question while trying to create a concise example.
It makes use of table layout:
.grid {
display: table;
table-layout: auto;
width: 100%;
}
.row {
display: table-row;
}
.expand {
display: table-cell;
width: 100%;
max-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.shrink {
display: table-cell;
white-space: nowrap;
}
The width: 100% in .expand is what makes the block fill all available space, thus fulfilling the first two requirements.
Note that the width in .grid simply sets the width of the entire grid, you can use any value here.
For some reason, putting max-width: 0 in .expand prevents the block to grow more than the available space, a smallish value like 100px will also do. I discovered this by chance and I don't know why it works.
Here's the jsfiddle: http://jsfiddle.net/fr253/
This answer helped me getting started.
I don't know whether my code is valid, but it gets the job done: either with grid or with flex.
.container {
display: grid;
grid-template-columns: 1fr auto auto;
}
.one {
background-color: pink;
}
.two {
background-color: yellow;
}
.three {
background-color: lightgreen;
}
/* Now the same but with flex. */
.whole-row {
grid-column: 1 / -1;
}
.flexy {
display: flex;
border: 1px solid red;
}
.flexy > .one {
flex-grow: 1;
}
.flexy > .two,
.flexy > .three {
/* flex-grow: 0; <- This value is a default. */
}
<div class="container">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
<div class="whole-row flexy">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
</div>
</div>