Auto fill and adjust cards in given container [duplicate] - css

This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed 3 years ago.
I have plenty of Angular mat-cards i.e. uncertain number of cards with images of different sizes.
What i am trying implement is a auto fill and adjustment of such cards depending on the container, something like this.
Now example above is using 4 columns and possible using grid.
Now, how do I implement that with cards? I tried using flex but somehow not able to properly implement it. Here's my worthless try.
<div class="mat-card-container" style="
display: flex;
justify-content: center; /* Add this */
flex-wrap: wrap;
">
<div class="mat-card-holder" style="
margin:0.6em;
width:220px;
" *ngFor="let art of arts.records">
<mat-card class="art-card" >
<mat-card-header>
<mat-card-title>{{ art.TITLE }}</mat-card-title>
<mat-card-subtitle>{{ art.AUTHOR }}</mat-card-subtitle>
</mat-card-header>
<img mat-card-image src="http://localhost/piwigo/{{ art.URL }}" alt="Photo of a Shiba Inu">
<mat-card-content>
{{art.TECHNIQUE}} / {{art.SCHOOL}} / {{art.FORM}} / {{art.TYPE}} / {{art.LOCATION}}
</mat-card-content>
</mat-card>
</div>
</div>
This is giving me this much, but still there are alot of gaps to be covered.
This is only lining them up in columns, how to i dynamically fill and adjust these in container? Assuming if container size changes, cards should rearrange without changing their own css i.e. dimensions. Is my code correct uptill? And how do i fill the gap in between?

To the extend of my knowledge, this layout style you are looking to implement cannot be achieved by css in of itself.
With some help from a javascript helper library, this is easily implemented. As you are using Angular, this is an Angular wrapper to the previous library which will permit to do such a design.
Replying from my phone and can't really reproduce your exact ui, but copying verbatim here their example implementation,
App.module.ts
import { MasonryModule } from '#thisissoon/angular-masonry';
const masonryProviders = [
{ provide: Masonry, useFactory: () => window['Masonry'] },
];
#NgModule({
imports: [MasonryModule.forRoot(masonryProviders)],
})
export class AppModule {}
angular.json
"scripts": [
"../node_modules/masonry-layout/dist/masonry.pkgd.js"
],
app.component.ts
export class AppComponent implements AfterViewInit, OnDestroy {
#ViewChild('grid') public grid: ElementRef;
public masonryInstance: MasonryInstance;
public cards = cards;
constructor(#Inject(Masonry) public masonry) {}
ngAfterViewInit() {
const options: MasonryOptions = {
itemSelector: '.card',
columnWidth: '.card',
gutter: 20,
fitWidth: true,
};
this.masonryInstance = new this.masonry(this.grid.nativeElement, options);
}
layout() {
this.masonryInstance.layout();
}
ngOnDestroy() {
this.masonryInstance.destroy();
}
}
app.component.css
:host {
display: block;
margin-top: 1rem;
}
.grid {
margin: 0 auto;
}
.card {
display: inline-block;
margin-bottom: 1rem;
width: 18rem;
}
app.component.html
<div class="grid" #grid>
<div class="card" *ngFor="let card of cards">
<div class="card-body">
<h5 class="card-title">{{ card.title }}</h5>
<p class="card-text">{{ card.text }}</p>
Go somewhere
</div>
</div>
</div>

Related

Set auto and fr grid template columns in Tailwind CSS?

I need to apply this line of CSS to my layout:
grid-template-columns: auto 1fr;
Is this something you can't do with Tailwind CSS?
You can extend the utilities using your Tailwind CSS config:
module.exports = {
theme: {
extend: {
gridTemplateColumns: {
'my-columns': 'auto 1fr'
}
}
}
};
<div class="grid grid-cols-my-columns">
</div>
Or you can use arbitrary values if you're only using this layout in one place:
<div class="grid grid-cols-[auto_1fr]">
</div>
There's more details in the documentation.

Unable to alter CSS styles by id

I have a very simple div in my footer:
import React from "react";
import { useHistory } from "react-router-dom";
import style from "./DesktopFooter.module.css";
const DesktopFooter = () => {
const history = useHistory();
return (
<div className={style.container}>
<div className={style.footerNav} id="phoneNumber">
999-999-9999
</div>
<div className={style.footerNav}>
</div>
<div className={style.footerNav}></div>
</div>
);
};
export default DesktopFooter;
In my CSS I want to style both on the class and id:
.footerNav {
width: 50%;
display: flex;
}
#phoneNumber {
font-size: 2rem;
}
However my component is not recognizing the id styling I try to apply.
Could anyone point me in the right direction.
Ya, After you update a question, I found the issue, you are try to load style for id as normal Dom, but its will not work since you are not include css file as is, you are import style file to style param...
so, what you need to do is replace id="PhoneNumber" to this
<div className={styles["footerNav"]} id={styles["phoneNumber"]}>
999-999-9999
</div>
Check the demo url
Full Code:
import React from "react";
import style from "./MyComponent.module.css";
export default function App() {
return (
<div className={style.container}>
<div className={style["footerNav"]} id={style["phoneNumber"]}>
999-999-9999
</div>
<div className={style.footerNav}></div>
<div className={style.footerNav}></div>
</div>
);
}
I would suggest having it as either a class or an id. Classes usually have a higher priority, meaning that the id will be ignored.
This is what it should look like:
.phoneNumber {
font-size: 2rem;
width: 50%;
display: flex;
}
<div class = "phoneNumber">999-999-9999</div>
However, if you would like to get around this, I would use another element within the div, such as:
#myID{
font-size: 2rem;
}
.phoneNumber {
width: 50%;
display: flex;
}
<div class = "phoneNumber">
<p id="myID"> 999-999-999 </p>
</div>
Ok I found a solution, or at least a work around. The problem seems to be that the file was a css module and not just a css file.
I changed the name of the css file from DesktopFooter.module.css to DesktopFooter.css
and I changed my import statement from
import style from "./DesktopFooter.module.css" to import "./DesktopFooter.css

React how to avoid css overide other components? [duplicate]

This question already has answers here:
How to make React CSS import component-scoped?
(6 answers)
Closed 1 year ago.
i am trying to create React aplication which uses AG-Grid table. Previously I customized table and removed borders of the ag grid by overiding css. I used this code to do so.
.ag-root-wrapper {
border: solid 0px !important;
border-color: var(--ag-border-color, white) !important;
}
But i noticed that code which i used only for one component has influenced whole aplication.
I was curious maybe is there way to locally import css only for specific component?
This is the way i was importing css for component
import './Statistics.css'
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
const Statistics = () => {
return (
<div className='content'>
<div className='content-left'>
<div className="ag-theme-alpine">
<AgGridReact
rowData={data}
style={{borderColor: 'red'}}
rowSelection="single"
filter={false}
>
<AgGridColumn
headerName="Date"
field="date"
resizable={true}
filter={false}
width={130}
flex={1}
sort={'asc'}
cellStyle={{fontSize: '1vw'}}
/>
</AgGridReact>
</div>
</div>
</div>
)}
export default Content;
When you use pure css or css preprocessors (Sass, less..), the imported css will always be global to your app. It is really useful to scope every component in a unique classname so you can scope css.
import './Statistics.css'
import { AgGridColumn, AgGridReact } from 'ag-grid-react';
const Statistics = () => {
return (
+ <div className='root-statistics'>
<div className='content'>
<div className='content-left'>
<div className="ag-theme-alpine">
<AgGridReact
rowData={data}
style={{borderColor: 'red'}}
rowSelection="single"
filter={false}
>
<AgGridColumn
headerName="Date"
field="date"
resizable={true}
filter={false}
width={130}
flex={1}
sort={'asc'}
cellStyle={{fontSize: '1vw'}}
/>
</AgGridReact>
</div>
</div>
</div>
+ </div>
)}
export default Content;
.root-statistics .ag-root-wrapper {
border: solid 0px !important;
border-color: var(--ag-border-color, white) !important;
}

How styling works over components in angular?

Question is not clear but I'll break it down. In angular we can write isolated css for styling. It works pretty well for native html elements. But unlike react, angular wrap our html with custom elements like <app-card>...</app-card>. When I write css for those wrapper elements, it doesn't work .
If I have a post list like
<div class="post-list">
<app-card [post]="post" *ngFor="let post of posts"></app-card>
</div>
If I write css to apply some vertical gap between app-card components in PostListComponent. Well nothing happens.
.post-list app-card:not(:last-child) {
margin-bottom: 2rem;
}
How can I make it work? Or with angular logic, how can I apply vertical gap between angular components
Just add display: block; on your app-card component & it will work as expected.
.post-list app-card {
display: block;
}
.post-list app-card:not(:last-child) {
margin-bottom: 2rem;
}
<div class="post-list">
<app-card>Card 1</app-card>
<app-card>Card 2</app-card>
<app-card>Card 3</app-card>
</div>
You can define encapsulation: ViewEncapsulation.None in your Component like this:
#Component({
selector: 'foo',
template: './foo.component.html',
styleUrls: ['./foo.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FooComponent { }
Which will treat your .css as the same if you were putting it in the global scope.
To be more accurate, it won't append .fooComponent to each css rule in foo.component.scss.
You can make the iteration in div tag then add your class
<div class="post-list">
<div class="post" *ngFor="let post of posts">
<app-card [post]="post"></app-card>
</div>
</div>
And in your css
.post-list .post:not(:last-child) {
margin-bottom: 2rem;
}
There is no reason it shouldn't work. Just tried to put in some of your code here. https://stackblitz.com/edit/angular-scss-demo-icqrye
app.component.html
<div class="post-list">
<app-new *ngFor="let item of [1,2,3,4]"></app-new>
</div>
styles.scss
.post-list app-new:not(:last-child) p {
margin-top: 2rem;
color: green;
}
And it works perfectly. Are you looking for something else?
And if you want to add the style (margins) to the component directly, you will first need to set the display of the component to block/flex as per requirement.
.post-list app-new:not(:last-child) {
display: flex;
}

How to center an ngx-bootstrap modal

Trying to center this ngx-boostrap modal using CSS like this but it's not working:
.modal.fade.in{
display: flex;
justify-content: center;
align-items: center;
}
But in the dev tool, I'm able to add CSS like this:
.modal.dialog{
top: 50%
}
So at least it is centered vertically, but this is in the dev tool, and there is no .modal.dialogclass in the html template
Is there a way to center properly the ngx-bootstrap modal ?
I want to create a generic modal component to use it anywhere, by providing an input message and adding a yes/no dialog and output the user choice (using EventEmitter)
I've found an example in the following Plunker, but not able to reproduce it in a separate custom component.
The plunker example comes from this website: https://github.com/valor-software/ngx-bootstrap/issues/2334
Update:
After #Wira Xie answer, when I use the Static modal and this CSS:
.modal-sm
{
top: 50%;
left: 50%;
width:30em;
height:18em;
background-color: rgba(0,0,0,0.5);
}
The modal shows centered, but only the Esc key can hide it, so when I click outside the modal, it's still visible.
Why not to use bootstrap modal-dialog-centered class:
this.modalRef2 = this.modalService.show(ModalContentComponent,
{
class: 'modal-dialog-centered', initialState
}
);
in the .ts file you have a code like this (to open modal popup)...
private showModal(template: TemplateRef<any>): BsModalRef {
return this.modalService.show(
template,
{ class: 'modal-lg modal-dialog-centered',
ignoreBackdropClick: true,
keyboard: false
});
}
You can see that I've added modal-dialog-centered to the class. after doing this you can also modify the modal-dialog-centered class in your css.
Try adding this attribute to your CSS: vertical-align: middle to your .modal.dialog class
Plunker for modal
.modal.fade {
display: flex !important;
justify-content: center;
align-items: center;
}
.modal-dialog {
vertical-align:middle;
height:18em;
background-color: rgba(0,0,0,0.5);
}
You need to use the bootstrap class.
Add .modal-dialog-centered to .modal-dialog to vertically center the modal.
import { Component, OnInit, TemplateRef } from '#angular/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
#Component({
...
})
export class ModalComponent {
modalRef: BsModalRef;
// Here we add another class to our (.modal.dialog)
// and we need to pass this config when open our modal
config = {
class: 'modal-dialog-centered'
}
constructor(private modalService: BsModalService) { }
openModal(template: TemplateRef<any>) {
// pass the config as second param
this.modalRef = this.modalService.show(template, this.config);
}
}
You have to pass the modal-dialog-centered bootstrap class for the BsModalService.show() function like this:
const initialState = {
organization: organization,
};
this.modalRef = this.modalService.show(AdminOrganizationCreateComponent, {
class: 'modal-dialog-centered', initialState
});
Note: if you need to pass initial data you can pass it using the initalState object.
A bit late, but for reference.
The reason the styling of the dialog in the component is not working, is because component styling is isolated and restricted to elements within the component. The dialog created through the bsmodalservice is outside of this component. (directly under <body>).
So, while your styling is encapsulated in the component and some random identifier, the dialog itself is not. The final css (like mycomponent[_ngcontent_bla_323] .modal) does not apply to the div.modal that is added by the service.
Possible solutions are:
Move your css for this dialog to some global (s)css file instead of the (s)css for the component
Instead of using bsModalService with a template, use the bsmodal directive with a div within your component. That way the component local (s)css will apply.
I have added mat-step inside the modal and because of that it didn't align centered for modal-dialog-centered bootstrap class ether. But modal-lg class worked for me. Sample code is very similar to the accepted answer. Only change the bootstrap class which is passed to the modal.
this.modalRef = this.modalService.show(AddDevelopersGroupComponent,{
class: 'modal-lg',
initialState,
});
This is a snippet from my personal project using ngx-bootstrap too.
.modal-sm
{
top: 50%;
left: 50%;
width:30em;
height:18em;
margin-top: -9em;
margin-left: -15em;
background-color: #001b00;
/*position:fixed;*/
}
<!--typecript files-->
<script>
//here is the typesciprt file
export class AppComponent
{
//for default ngx-bootstrap modal
public modalRef: BsModalRef;
constructor(private modalService: BsModalService) {}
public openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template);
}
}
</script>
<!--end of ts file-->
<!--Modal-->
<div class="container">
<div bsModal #smModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title pull-left">Small modal</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="smModal.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>
<!--enf of modal-->
According to the documentation you can center the modal vertically via setting centered property to true (as it is false by default)
const modalRef = this.modalService.open(ConfirmationDialogComponent, {
size: dialogSize,
centered: true
});

Resources