So i'm fetching "boxes" and dynamically adding them into the HTML document with ngFor. I don't know in advance how many of them will be there. Currently i'm using this code:
<div *ngIf="items && items.length" class="row">
<div *ngFor="let item of items"
class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-4">
<app-single-item [item]="item"></app-single-item>
</div>
</div>
What that gives to me:
Which is okay but the problem is I want bigger spacing between those elements. It should look like this:
To achieve the look on the second image I put width: 21% to col-xl-3 and added display: flex and justify-content: between to the row div.
But the problem is, now if I have less than 4 boxes in a row, the spacing between them is much bigger. You can see it on the image below
My question is how can I get the same spacing between boxes regardless of the number. I don't want to use fixed width on the item divs that's why I use cols. and this is important, I need those items to always show from the beginning of the outer div, so in line with the element above it. Thanks.
Simply you can use margin right class of bootstrap for each column so that it appears to take some margin from right column like this
<div *ngIf="items && items.length" class="row">
<div *ngFor="let item of items"
class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-4 mr-3">
<app-single-item [item]="item"></app-single-item>
</div>
</div>
Keep width and use justify-content-center
Edit based on comment-
Apply container class to outer div and use -
#include media-breakpoint-down(lg) {
.container {
width: 100%;
max-width: none;
}
}
Instead updating the margin or width of your elements, you should update the padding, because it won't affect the outer but the inner element.
Code example (not tested)
<div *ngIf="items && items.length" class="row">
<div *ngFor="let item of items"
class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-4 pr-2 pl-2">
<app-single-item [item]="item"></app-single-item>
</div>
</div>
Then with those principles, you can choose the space you want between elements.
And plus, maybe you don't want the first and last elements having left and rightpadding, so you may use media-queries breakpoints to remove pl-2 from first element and each 2n elements for the sm breakpoint for example, and pr-2 from second element and each 2n+1 elements for the sm breakpoint, (and an other math for other breakpoints, depending on how many elements are displayed by row).
See the doc
Related
I have been working on a game and, for certain things, I used absolute positioning. In particular, I need it for some moving animations where I have to slide elements around and overlap them to create an effect.
I'm trying to work on making the game good-looking on mobile, and I've been running into some problems caused by Bootstrap columns that contain those absolutely positioned elements.
This is the look I'm trying to get (aside from the badly aligned number), notice the red squared row in the middle:
The whole center part of the screen (the row with buttons, emojis, and the centered card icon underneath) is a row containing cols. This is some of its markup
<div class="col order-1 order-xl-1 col-4 col-xl-2">
<div style="display:inline-block">
<p class="backgrounded-text" style="white-space: nowrap; text-overflow: ellipsis;"><span id="turn_elem">...</span></span></p>
<p class="backgrounded-text">Carta attuale: <span id="curr_card"><img class="card_icon" /></span></p>
</div>
</div>
<div class="reaction_box order-2 order-xl-2 col col-4 col-xl-2">
<span style="padding-left:5px!important;padding-right:5px!important" class="reaction_title">Reazioni:</span>
<table>
<!-- emojis ... -->
</table>
</div>
<div class="col order-5 order-xl-3 col-12 col-xl-3">
<span>...</span><br />
<span id="hidden_card">
<img class="card_placeholder" src="..." />
</span>
<span id="card_stack" class="slide_to_right">
<img class="card_placeholder" src="..." />
</span>
<div id="stacked_card">
<img id="stacked_front" class="card_placeholder" src="..." />
</div>
<div id="hidden_uncovered_card_div">
<img id="hidden_uncovered_card" class="card_placeholder" src="..." />
</div>
</div>
<div class="col col-4 order-3 order-xl-4 col-xl-3">
<button style="width: 49%" class="btn btn-lg btn-dark" id="doubt" #click="doubt()" :disabled="playing_animation">Dubito!</button>
<button style="width: 49%" class="btn btn-lg btn-dark">
Metti giĆ¹
</button>
</div>
</div>
The img that has id hidden_card is a card to the left of the red one that is made visible and slides to the right to cover that (it uses jQuery animate to manipulate the position). On top of stacked_card, which is the main red card that's displayed in the screenshots, there's another copy of it, that is flipped with jQuery and moved to the right to overlap hidden_uncovered_card. This is pretty much how the animations work. They all depend on using position: absolute and manipulating the positioning.
For some reason, the actual look I'm getting with the above code is this:
There is some space in between the three columns on the top and the one containing the red card back, and I don't understand where it is coming from.
Removing all the position: absolute seems to fix this, but of course, then all the animations that depend on it stop working.
Is there any way to fix this positioning without removing the position: absolute? It'd be a pain to have to rewrite the code for all the animations, as it's working perfectly on desktop.
Here's a static webpage that contains the markup. You can turn it to mobile view (the screenshots were taken as iPhone 6/7/8 mode) and see for yourself.
click
The actual app (a beta version, that is) can be found here, in case you wanted to see how the animations work. If you need any additional information, just let me know.
Bootstrap is using a 12 colums grid.
Check how you use them.
You have:
<div class="col order-1 order-xl-1 col-4 col-xl-2">The two button on the left<div>
<div class="reaction_box order-2 order-xl-2 col col-4 col-xl-2">the emojis</div>
<div class="col order-5 order-xl-3 col-12 col-xl-3">the red cards</div>
<div class="col col-4 order-3 order-xl-4 col-xl-3">the three button on the right</div>
You should clean that!!!
Example:
col followed by col-4 is the same as just col-4 where col-4 overrides col.
order-1 and order-xl-1 is redondant if there is no order-md-3 (for example)
Just order-1 is enought here.
For these 4 divs, make sure you use the 12 grid spaces correctly.
So about the col and col-* usage, for mobile size, you actually have 24 spaces used out of 12.
4 spaces
4 spaces
12 spaces
4 spaces
And whent the col-xl-* applies, you have 10 spaces used out of 12. Is that on purpose?
2 spaces
2 spaces
3 spaces
3 spaces
So here is what I suggest for a start:
<div class="col-3 col-xl-2 order-1">The two button on the left<div>
<div class="reaction_box col-4 col-xl-2 order-2">the emojis</div>
<div class="col-2 col-xl-3 order-3">the red cards</div>
<div class="col-3 order-4">the three button on the right</div>
which doesn't change the xl size at all, but produces this (iphone 6/7/8 mode):
That's a start.
So the trick is to have the classe in order... All the col-* from default to the bigger specific size... And then the order-* in order too. That make the markup readable.
;)
EDIT
To have the red cards looking like on another row :
<div class="col-4 col-xl-2 order-1">The two button on the left<div>
<div class="reaction_box col-4 col-xl-2 order-2">the emojis</div>
<div class="col-10 col-xl-3 order-4 order-xl-3 sm-translateUp">the red cards</div>
<div class="col-4 order-3 order-xl-4">the three button on the right</div>
Notice the order changed and that there is an additional .sm-translateUp class which would be:
#media screen and (max-width: 576px){
.sm-translateUp{
transform: translateY(-85px);
}
}
That makes:
Now that really looks like a hack... (LOL) But since that col is trapped inside its parent .row, that is all I think of for the moment.
So have that class defined inside all necessary #media rules for each bootstrap break points:
sm: >= 576px
md: >= 768px
lg: >= 992px
xl: >= 1200px
I am using bootstrap 4. Below is my html
<div class="container">
<div class="row text-center ">
<div class="col-lg-6">A</div>
<div class="col-lg-6">B</div>
</div>
</div>
This code works fine on the website. However, on mobile or when I resize the browser to be very narrow, the 2 classes col-lg-6 stack on top of each other with quite a lot vertical space between them. I wonder is there any way to reduce that space?
space could be caused by either margin or padding... to set:
padding bottom to zero, use class pb-0
padding top to zero, use class pt-0
margin bottom to zero, use class mb-0
margin top to zero, use class mt-0
this is the bootstrap way... more info here
I have some components that is generated by a for-loop based on number of objects from the server, that is going to be displayed on frontend,
<div class="container-fluid">
<div class="component">
<div class="row card">
<app-component class="list-group-item col" [User]="comp.user"
[title]="comp.title"
*ngFor="let comp of component"></app-component>
</div>
</div>
</div>
I want the components to be aligned in the middle while the last row will align left. The current situation is that the components is align center, when I want the last row of components to align left.
How our current html looks like
The margins on each side remain equal related to number of components.
The component has a fixed size, and as the screen is bigger (or adjusted) it will fit more component in each row while the gap between the components expands.
How it looks like when the screen adjust to bigger
As in the image there is even components, but if there were 1 more component it would be placed in the center of a third row. In that case, I want the last component to be placed left in a third row.
this is our current scss file:
.component {
display: inline-block;
margin-right: 10%;
margin-left: 10%;
> .card {
display: flex;
flex-wrap: wrap;
> app-component {
margin-top: 2rem;
margin-right: 3rem;
}
}
}
The main problem is that all the component is generated by a for-loop based on how many object i get from server. therefor i cant customize each component for them self
I'm not sure I quite undetsand well your needs.
Either look at flexboxes : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Or why don't you use BS4 columns grid ???
Furthermore, you mix components and grid classes : Only col can be children of rows.
<div class="component">
<div class="row">
<div class="col-md-4">
<div class="card">
CARD CONTENT GOES HERE
</div>
</div>
</div>
</div>
Tell us more about your research.
By using grid system of bootstraps 4, it can define how many columns an element in HTML will use based on the screen size and resolved my problem.
<div class="container root">
<div class="row">
<div class="col-12 col-md-6 col-lg-4 col-xl-3 card"
*ngFor="let comp of component>
<app-component [user]="comp.user"
[title]="comp.title"></app-component>
</div>
</div>
</div>
The bootstrap class take based on the size of the screen and change classes, you can read more about it at https://getbootstrap.com/docs/4.1/layout/grid/
I am new to bootstrap 4 and haven't worked on bootstrap 3 much either.
When I assign a class col-(breakpoint)-(span) to div(s), they don't automatically arrange in a single row or adjust according to the width of the window, instead they remain left aligned and stacked on top of one another. So I assign CSS flex property to the parent container and that does the trick.
Now to make these wrap according to the window size I assign classes according to bootstrap 4 grid system, but that does not make the containers wrap to the next row. Instead the combined width of the flex-items exceeds the width of the window, enabling sideways(x-axis) scroll.
What I want is that the first two containers remain in one row and last two wrap to another row on smaller screen widths(phone portrait, <576px).
<div style="display:flex;">
<div class="col-sm-3 col-6"></div>
<div class="col-sm-3 col-6"></div>
<div class="col-sm-3 col-6"></div>
<div class="col-sm-3 col-6"></div>
</div>
Where am I going wrong?
Use all necesarry grid classes, see the docs https://getbootstrap.com/docs/4.0/layout/grid/
You have to wrap all cols in row and rows in container (.container or .container-fluid)
<div class="container">
<div class="row">
<div class="col-sm-3 col-6">x</div>
<div class="col-sm-3 col-6">y</div>
<div class="col-sm-3 col-6">z</div>
<div class="col-sm-3 col-6">a</div>
</div>
</div>
Try this to remove the style attribute that contais flex and add instead a class="row" and for the child divs replace the classes with this class="col-lg-3 col-md-3 col-6"
I'm trying to reorder the columns on my website via Bootstrap's method of reordering columns depending on the screen size which works fine for most of the responsive layouts I'm testing apart from 1.
The layout having problems is the Tablet Landscape Layout (1024 x 768) which displays like this:
Every other screen displays the blue div and the right div either with the red div on top if the screen is too small or on the right with the blue div aligning itself exactly next to it if the screen is large enough.
This is the code I'm using right now:
<div class="container">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="row clearfix">
<div class="col-xs-12 col-sm-12 col-md-push-8 col-md-4 col-lg-push-8 col-lg-4 col-xl-push-8 col-xl-4" style="background: red">
Basket
</div>
<div class="col-xs-12 col-sm-12 col-md-pull-8 col-md-8 col-lg-pull-4 col-lg-8 col-xl-pull-8 col-xl-8" style="background: blue">
News
</div>
</div>
</div>
</div>
Does anyone know why the blue div is so far to the right on the Tablet Landscape layout rather than touching the red div like it should?
Some general markup issues:
First of all, there's no col-xl-*, so you can get rid of those.
Secondly, you don't need col-xs-12, since the default is for it take up the whole width unless otherwise specified.
Third, Bootstrap is mobile first, so larger sizes will override the existing smaller sizes, meaning if you don't intend on changing something, there's no need to specify the larger size again.
The actual issue is that col-*-pull-* is relative to where the element would be placed. Bear in mind, you haven't changed anything in the document flow. So the elements are positioned normally and then phase shifted with left or right. Since the blue container would normally start 4 columns over, you only need to pull it back by 4 columns, instead of 8.
The whole thing can be rewritten like this:
.red { background: red }
.blue { background: blue }
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<div class="container">
<div class="row ">
<div class="col-md-4 col-md-push-8 red"> Basket </div>
<div class="col-md-8 col-md-pull-4 blue"> News </div>
</div>
</div>