I have a parent section div with a max-width of 1760px.
I can put a carousel directly inside a section container and it will take the width of the viewport up to 1760px i have set, works as expected. *carousel will try to fill 100% of space given.
However, the issue is that i want to put the content inside a 2 col grid, inside container, but the first part of the grid has the carousel that takes the max-width of parent section, rather than stopping at width of page. So, rather than take 2fr of the viewport (map takes 1fr), it fills whole of 1760px so the screen overflows.
Style wise, The best example i can find online to show what i mean is Airbnb listing, it has 2 cols, 1 with listing and 1 with map. This is pretty much what i am trying to replicate.
Here is the carousel directly in section (pretty simple and works as explained above). If i put the carousel inside this it doesn't overflow page.
<section>
<div>Carousel</div>
</section>
section{
max-width: 1760px;
padding: 50px 40px;
margin: 0 auto;
}
Once i add it inside a grid it ignores the viewport size and simply fills max-width of section (1760px) and overflows viewport width.
<section>
<div class="grid">
<div>Carousel</div>
<div>Map</div>
</div>
</section>
.grid{
display: grid;
grid-template-columns: 2fr 1fr;
grid-gap: 20px;
}
It actually works using grid-template-columns: 60% 40%; instead of 2fr 1fr, and removing margin: 0 auto. But this means i cannot use gap (which is fine).
To summerize, how can i use fr sizing and make sure it takes notice of viewport size, and not just take up the max-width value by default.
I went through your pen and made some changes and it gave the result as you wanted it to be, no overflowing of the image.
If you do following changes, it will work for you too:
These are not mandatory, if you wish you can do the changes or else you can keep as it is.
Remove the max-width: 1760px from section style.
Add max-width: 1760px to the grid element, since you are providing the max-width to the grid, the parent section will also have this max-width, since grid is the child element.
Now make sure you are applying the width: 100% to the images (This is mandatory). Like this:
.listing > img {
width: 100%;
}
OR, if you have nested elements inside .listing element and img tag is not the immediate child of the .listing element, then you can go with this way:
.listing img {
width: 100%;
}
So every img tag which is direct or indirect descendent of .listing element will have width 100%
Here's the working piece of example:
https://codepen.io/prathameshkoshti/pen/KKMYoWY?editors=0100
Related
I am trying to use an implicit CSS grid to generate a layout for the following basic HTML structure:
<div class='row'>
<textarea></textarea>
<div></div>
</div>
where the .row div is a CSS grid with an auto-flow set to column for automatically placing elements as columns:
.row {
display: grid;
grid-auto-flow: column;
}
I would expect, as with most elements, that the CSS grid would provide equal space to both the textarea and the div elements along the row. But instead, the layout looks like this:
The textarea takes up more space along the row than expected. When you try to resize the textarea, I see the following:
What seems to be happening here is the grid is adding additional space to the right of the textarea equal to the width of the div on the right. What I can't figure out is why this is happening, and why the elements don't initially have an equal width. What am I missing here?
I've created a simple JSFiddle for testing this behavior here.
To make them the same size you need to ask the grid to do that
grid-auto-columns:1fr;
You can stop the user resizing the textarea with resize:none
If you want to get this to work whilst letting the user resize, I couldn't find a css solution
I had an idea but I couldn't get it to work.
The gist was
have a set of [invisible] divs as a first row
have a function that can be called on an element of a grid to see if its offsetWidth is lesser to one of the hidden divs of the same column
if it is, manipulate the css from auto to setting the width explicitly to the textarea's for that column, then with some mix of repeat(x, 1fr) (pre-textarea columns) & repeat(auto-fill, 1fr) (post-textarea columns)
then attach this function to the resize (or mouseup) of the textarea
Alternatively, consider flex.
It will have the opposite problem; it wont force an element to be 1fr (and apply that unwanted padding), but I dont think you can ask it to be 1/<number in row> in size [in css only] either.
why the elements don't initially have an equal width. What am I missing here?
textarea has a width initially defined by cols which has a default value equal to 20
cols
The visible width of the text control, in average character widths. If it is specified, it must be a positive integer. If it is not specified, the default value is 20.
This width play a role in defining the initial width of the textarea. You can set a small value to make sure it behave almost the same as div.
.row {
display: grid;
grid-auto-flow: column;
}
.row > div {
border: 1px dotted;
}
<div class='row'>
<textarea cols=1></textarea>
<div></div>
</div>
You can still notice a small difference since the textarea is not having an initial width exactly equal to 0 and it also has some padding so its column will logically be a little bigger.
To avoid this and to also fix the resize issue better explicitely define the grid like below where you set the initial width of the textarea to be half the width of grid.
I don't know your real use case but I will consider the fact that your grid is full page width (I will also consider the default body margin)
.row {
display: grid;
grid-template-columns:auto 1fr;
}
.row > div {
border: 1px dotted;
}
textarea {
width:calc(50vw - 16px);
box-sizing:border-box;
}
<div class='row'>
<textarea ></textarea>
<div></div>
</div>
I have made a css grid layout in a sample portfolio page i have made, when i did it with just html / css it worked fine and was responsive: The code is here:
https://codepen.io/abhinavthinktank/full/YevQNq/
The one which isn't responsive is hosted here:
https://abhinav-m.github.io/
The react components for the same are here: https://github.com/abhinav-m/personal-portfolio/tree/master/src/components
I made the same using react, sass and node, however this one is not responsive, to be exact the div with the class techStack is not resizing.
Here's the grid layout css:
.gridContainer {
display: grid;
grid-template-rows: 15px 10% 20% 10% 20% 20% 20% 25px;
grid-template-columns: 10% 80% 10%;
grid-row-gap: 25px;
justify-items: center; }
and the div class='techStack' css:
.techStack {
grid-row: 6 / 7;
grid-column: 2 / 3;
background: bisque; }
The CSS of both of these appear to be the same! I can't understand why one of these is not working.
LINK FOR JSFIDDLE : https://jsfiddle.net/69z2wepo/121098/ (not responsive)
Your image icons (.dev-icon-* colored) are a list of inline-level ::before pseudo-elements, which are each contained inside an inline-level i element, which are all contained inside a block-level div element.
The icons are provided by a third party service (devicon).
For whatever reason, these pseudo-elements, as devicon icons, don't wrap.
However, if you switch out the devicon code (e.g. content: "\e845") with plain text (e.g. content: "text text text text"), then the pseudo-elements do wrap.
Alternatively, if you switch the div container from display: block (the default) to display: flex, the devicons wrap, as well.
So the problem seems to boil down to devicons in a block container.
Here's a simple overall solution:
div.icons {
display: flex;
flex-wrap: wrap;
}
I had a look but I can't work out what the cause of the difference is. I'm guessing it's a style somewhere else on the page or because of a slightly different structuring of elements.
However, if you set the style of your icons to display: inline-block then it fixes your problem.
I'm currently trying to get an element (div) stretching itself over the free space of a parent element while respecting the size of other elements on its level. I found some solutions and tried most of them but I couldn't get it to work. I suspect this is because of the cms I'm working with which - when telling it to make a set of columns the same height - changes the parent display-style to table-cell. So... here is an image of what I'm trying to archive.
As said, the CMS changes the blue container to display: table-cell to stretch it over the whole area and make all columns in a row the same height. Inside of this blue container are the elements I can control. These are up to four div (white/green) inside of a parent div (yellow). The white div are dynamic and not always present and the green one needs to stretch over the whole vertical space no matter which of the white elements are present.
And idea how to accomplish that? I tried a lot of answers about this topic but they didnt work.. I think that's maybe due to the fact that the blue container is a table-cell?
edit: Here is what I got so far.
<div id="box_wrap">
<div class="box_title">
Title
</div>
<div class="box_image">
Image
</div>
<div class="box_content">
Content
</div>
<div class="box_more">
Read More
</div>
</div>
All of this is in a container provided by the CMS itself which has the attibute display: table-cell.
#box_wrap {
display: flex;
flex-direction: column;
}
.box_content {
display: flex;
flex: 2;
}
I think the problem might be that the container provided my the CMS has no defined height. If I give my #box_wrap a fixed height manually then the div in it will work as they should. I also tried height: auto and height: 100% for the #box_wrap and it doesn't work. Again, probably because the parent has no defined height, no? That is the last thing that I need to solve. The #box_wrap needs to stretch over the vertical, currently it only extends as far as it needs to cover the content.
I also noticed that the first image I provided wasn't 100% accurate so I updated it.
I would use this to allow the .box_content to grow (i.e. become higher) and the others not:
.box_title,
.box_image,
.box_image {
flex-grow: 0;
}
.box_content {
flex-grow: 1;
}
In addition, you should apply height: 100% to #box_wrap, but for that you also need height: 100% on body and html to have a reference for the height of #box_wrap. So, to sum up:
html, body {
height: 100%;
margin: 0;
}
#box_wrap {
height: 100%;
}
You also might want to add...
body {
padding: 10px;
box-sizing: border-box;
}
...to get that distance between the edge of the screen and your container as it's shown in your image.
I am using the new css grid like this:
#site {
display: grid;
grid-template-columns: 10% 1fr 1fr 1fr 10%;
grid-template-rows: 100px auto;
grid-template-areas:
". header header header ."
". content content sidebar ."
}
So I have tow rows and 5 columns but only 3 columns with content. I'm using the dot in the template areas to define a white space.
This results in having a 3 column layout with white space on the left and right side.
If I place an element in a grid area that has a background color the white space left and right stays white (logically).
What I want is a full width background (color) but I'm not really sure how to realise this. One option I have in mind is to have a second grid in the background that has the same columns and rows but not the white spaces and then I can fill it up with color but I think this is not best practice.
Best I have found is put the grid inside a container for a certain width to center the content. And have items you need to extend the background give a huge left/right padding, and same margin negative.
Just be sure to give body an overflow-x: hidden;
<div class="container">
<div id="site">
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
</div>
And the CSS:
.container{
width:1000px;
margin: 0 auto; //
}
#site {
display: grid;
grid-template-columns: 10% 1fr 1fr 1fr 10%;
grid-template-rows: 100px auto;
grid-template-areas:
". header header header ."
". content content sidebar ."
}
.header{
background: red;
padding: 0 3000px;
margin: 0 -3000px;
}
body{
overflow-x: hidden;
}
I see 3 options here
You can set one or multiple backgrounds using CSS background color. Also this way you can set gradients and solid color can be imitated using gradients.
Create grid item with background and manually set grid-row and grid-column with values that you need. This items should have negative z-index to be overlapped by other grid items (z-index is working even for statically positioned for grid items, the same is true about flex items).
Absolutely positioned elements of grid container.
It sounds like what you're looking to do may be best addressed by the upcoming Subgrid feature, arriving in Level 2 of CSS Grid: this will allow outer elements and their children to both be laid out using the same grid.
As of today (Aug 8th, 2019) Subgrid has shipped in Firefox nightly, so will hopefully land in a real release soon (tracked here). Unfortunately, there hasn't been much movement yet from the Chrome team (please star the issue in the Chrome bug tracker to show your support)
In lieu of Subgrid arriving, what I've done is either define the same grid lines inside the container element, or, for the specific case of a full-width background, define a padding on the wrapper element that is equal in size to the width of the "empty" gutters on either side of the page. This is easiest/most reliable if you use vw units, and is fairly straightforward with the use of a variable in SASS or LESS
Just like www.stackoverflow.com for example, only uses the centre of the page while retaining the header at the top.
See my layout so far - it uses the whole screen whether its resized or maximised.
So basically I want to retain the header at all window sizes, but use only the centre of the page for the other 3 divs.
First thing you need is some wrapping element that "contains" the entire website. For example...
HTML
<body>
<div class="wrapper">
<!-- REST OF SITE HERE (OR ANYTHING YOU WANT CENTERED -->
</div><!-- END WRAPPER -->
</body>
Then some simple CSS... The wrapper element MUST have some width that you define, and a specific margin code. If the site is responsive, you want a dynamic width, with an additional max-width. In the code below, it is the margin: 0 auto; that actually does the centering. It's important to note the width however. If you have 100% width, without a max-width also declared, then the "centering" isn't noticeable as the div takes up 100% of the width of whatever element contains it.
CSS
.wrapper {
width: 100%;
max-width: 960px;
margin: 0 auto;
}
If you don't want the entire website to be centered, simply change your HTML a little bit, and maybe your class name so that it makes more sense in the context that it is being used... For example, if you want just the content area to be centered...
HTML
<body>
<header></header>
<div class="content-wrapper">
<!-- ALL OF YOUR CONTENT HTML HERE -->
</div><!-- END CONTENT WRAPPER -->
<footer></footer>
</body>
CSS
.content-wrapper {
width: 100%;
max-width: 960px;
margin: 0 auto;
}
It's always a good practise to wrap your container in any kid of wrapper (say div) and then asssign css margin: 0 auto; so that it centrally alligns to the screen.
Eg:
<div class="wrapper">
All the stuff in here
</div>
.wrapper{
margin: 0 auto;
// Along with other reset style sheets
}
I suggest you to use calc() in css. Differently from other solutions proposed by others, with the following code:
.wrapper
{
width:calc(100% - 50px);
margin:0 auto;
}
you can have wrapper div always centered and primarily flidly adaptable to Browser window width, leaving always the same amount of px to both margins. So if you change window width, it will be only the width of Wrapper that will change and not it's margins from sides.
UPDATE:
For IE8 retro-compatibility, there are some js polyfills, like:
Calc-Polyfill
Polycalc
Set width of the header to 100% and the width of the container to e.g. 80% with margin:0 auto;
Here is a fiddle
Also, it's a good thing to set margin and padding of the html and body to zero to get rid of the whitespace around your page
You can do a bad trick (but easy) with two divs (the second one inside the first one). The first one will have margin-left 50% and, only if you know the widht px of your page, the second div will have margin-left: -ZZZpx, being ZZZ the half of your width size.