CSS GRID vertically align text so it dosn't leave the container - html

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.

Related

CSS Grid - position text in three columns

currently I’m struggling with positioning these 3 text columns just like in picture. Each column contains 3 patagraphs.
Problem is, paragraph’s width is not equal, so grid-template-columns:repeat(3, 1fr) is not ideal solution because second and third paragraph will have unnecessary big white-space and that’s the problem when responsibility comes in. (Layout will break very soon because of that white-space).
I’ve tried min-content or max-content atributes but still I can’t figure it out, so it will look just as in the picture.
So goal is to align columns and paragraphs in it just like in the picture but without unwanted whitespace so work with responsibility will be easier.
Is there any better solution for it?
I have tried my best, here’s codepen
Thank you!
You can use minmax in your grid-template-column property, minmax(5rem, 10rem) minmax(3rem, 5rem) auto;, this will set the minimum width of the first column to 5rem and the maximum width to 10rem, the second to min of 3rem and max of 5rem, then the last columns width will be the width of its content => auto.
css-grid-layout-minmax ~ MDN
.card {
background: silver;
padding: 0 1rem;
border-radius: 12px;
}
.column {
display: grid;
grid-template-columns: minmax(5rem, 10rem) minmax(3rem, 5rem) auto;
justify-content: flex-start;
}
p:nth-of-type(3),
p:nth-of-type(4),
p:nth-of-type(2) {
text-align: right;
}
p + p {
margin-left: 1rem;
}
<div class="card">
<div class="column-wrapper">
<div class="column">
<p>lorem:</p>
<p>282726€</p>
<p>28%</p>
</div>
<div class="column">
<p>lorem ipsum:</p>
<p>287€</p>
<p>10%</p>
</div>
<div class="column">
<p>lorem:</p>
<p>19118€</p>
</div>
</div>
</div>

Control size of images in nested grid layouts

I'm trying to get into the grid layout system and I'm really struggling with image-sizes inside grid containers. I just want to create a simple page with a navbar. The navbar should contain a logo, icons and text. It is divided into three parts:
A left part, containing the logo (aligned to the left side)
A center part, containing a title (aligned to the center)
A right part, containing an image and text (aligned to the right side)
Because I want to work with grid whenever possible my planned structure looks like this: https://codepen.io/Nicolas_V/pen/QWbvxoW
HTML:
<div class="site">
<div class="navbar">
<div class="navbar__area--left">
<div>Logo</div>
</div>
<div class="navbar__area--center">
<div>Admin Page</div>
</div>
<div class="navbar__area--right">
<div>Text</div>
<div>Image</div>
</div>
</div>
<div class="content">Content</div>
</div>
CSS:
html, body{
margin: 0;
padding: 0;
}
.site{
display: grid;
grid-template-rows: 1fr 9fr;
height: 100vh;
}
.navbar{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
background-color: green;
}
.navbar > div > *{
display: inline;
margin-right: 2rem;
margin-left: 2rem;
}
.navbar__area--left{
text-align: left;
}
.navbar__area--center{
text-align: center;
}
.navbar__area--right{
text-align: right;
}
I created three containers for each part, so I can align their contents separately. So far so good.
Now I added a test image to the left part and expected it to fit to the containers height. But it doesn't.
https://codepen.io/Nicolas_V/pen/XWbRYLR
What i don't understand is, that if I REMOVE the enclosing container from the left side, the image perfectly fits to the height of the navbar as expected previously.
https://codepen.io/Nicolas_V/pen/rNVmrNm
But I need to have this container, because for the right part I want multiple items in the container, all aligned to the right side.
I know, that I can set fixed heights for images and so on, but I want to dig into the grid system and I'm sure there is a way to solve my problem.

Alternating CSS Grid columns and mobile view

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;
}
}

Align 3 elements using flexbox [duplicate]

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).

CSS grid where one column shrinks to fit content, the other fills the remaning space

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>