how to remove the height between these cards - css

The height of these cards are variable here I'm using angular material library and bootstrap
I need to reduce the horizontal space between the cards
you can see the cards iron throne and woman's image have taken too much space between them
this is the HTML of item-list component, I'm using Bootstrap and angular material
<div class="row">
<app-item *ngFor="let item of items" [item]="item"></app-item>
</div>
here's the ts code
import {Component, OnDestroy, OnInit} from '#angular/core';
import {Subscription} from "rxjs";
import {Item} from "../../models/item.model";
import {ItemsService} from "../items.service";
#Component({
selector: 'app-item-list',
templateUrl: './item-list.component.html',
styleUrls: ['./item-list.component.css']
})
export class ItemListComponent implements OnInit, OnDestroy {
items: Item[] = [];
isLoading = false;
totalItems = 0;
// itemsPerPage = 2;
// currentPage = 1;
// pageSizeOptions = [1, 2, 5, 10];
private itemsSub: Subscription;
constructor(private itemsService: ItemsService) {
}
ngOnInit(): void {
this.isLoading = true;
this.itemsService.getItems();
this.itemsSub = this.itemsService.itemsUpdateListener.subscribe(items => {
this.isLoading = false
this.items = items
})
}
ngOnDestroy(): void {
this.itemsSub.unsubscribe();
}
}
here's the HTML of ItemComponent
<div class="col-lg-3 col-md-4 col-sm-6">
<div class="card" style="width: 18rem;">
<a routerLink="">
<div class="card-img-wrap"><img class="card-img-top" [src]="item.imagePath" [alt]="item.title"></div>
</a>
<div class="card-body">
<span class="card-title">{{item.title}}</span>
<br>
<span class="card-text" style="margin-right: 3px">Rs. {{item.price}}</span>
</div>
</div>
</div>
in the ts of itemComponent there is only one property
#Input() item: Item;
and here's the css of ItemComponent
.card-img-wrap {
overflow: hidden;
position: relative;
}
.card-img-wrap:after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(255,255,255,0.2);
opacity: 0;
transition: opacity .6s ease-in-out;
}
.card-img-wrap img {
transition: transform .6s ease-in-out;
width: 100%;
}
.card-img-wrap:hover img {
transform: scale(1.1) ;
}
.card-img-wrap:hover:after {
opacity: 0.5;
}

Related

Change CSS class on click in Stenciljs

Is it possible to use the simple menu animation from W3School in Stencil.js?
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_menu_icon_js
I'm trying to set the styling on a click event, but I can't make it work. The event is fireing but I can't set the class.
In my .tsx:
import { Component, Prop, h } from '#stencil/core';
#Component({
tag: 'topbar-component',
styleUrl: 'topbar-component.css',
shadow: true
})
export class Topbar {
private menuToggle(e) {
return (
e.classList.toggle("change");
);
}
render() {
return (
<div class="topbar-menu">
<div class="container" onClick={(e) => this.menuToggle(e)}>
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</div>
)
}
}
In my css:
.bar1, .bar2, .bar3 {
width: 35px;
height: 5px;
background-color: #333;
margin: 6px 0;
transition: 0.4s;
}
.change .bar1 {
-webkit-transform: rotate(-45deg) translate(-9px, 6px);
transform: rotate(-45deg) translate(-9px, 6px);
}
.change .bar2 {opacity: 0;}
.change .bar3 {
-webkit-transform: rotate(45deg) translate(-8px, -8px);
transform: rotate(45deg) translate(-8px, -8px);
}
I get error: Uncaught TypeError: Cannot read property 'toggle' of undefined
You could do it using a state property:
import { Component, Prop, State, h } from '#stencil/core';
#Component({
tag: 'topbar-component',
styleUrl: 'topbar-component.css',
shadow: true
})
export class Topbar {
#State() isMenuOpen: boolean = false;
private menuToggle() {
this.isMenuOpen = !this.isMenuOpen;
}
render() {
return (
<div class="topbar-menu">
<div class={{ container: true, change: this.isMenuOpen }}" onClick={(e) => this.menuToggle(e)}>
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</div>
)
}
}
I made it work. I found the classlist at last.
So just add this to your menuToggle()
private menuToggle(e) {
return (
e.currentTarget.classList.toggle("change")
);
}
I think the following code can be usefuel for handling your question:
import { Component, Prop, h } from '#stencil/core';
#Component({
tag: 'topbar-component',
styleUrl: 'topbar-component.css',
shadow: true
})
export class Topbar {
private menuToggle() {
this.isMenuOpen = !this.isMenuOpen
}
render() {
return (
<div class="topbar-menu">
{this.isMenuOpen
?
<div class=container change" onClick={() => this.menuToggle()}>
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
:
<div class=container" onClick={() => this.menuToggle()}>
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
}
</div>
)
}
}

Angular: animation display card on top of another card

Im using angular animation builder for creating an animation. I have a grid list with a list of cards. When i click on a button ,i want another div to come on top of the initial card (float in from the left to cover the first card
) .As of now,the div comes in with the animation ,but is showing up on side of the initial card.I have made a stackblitz example to show the current progress.Here is my stackblitz:
https://stackblitz.com/edit/angular-ty4rfh
Also pasting the code here:
import { Component,OnInit,ElementRef } from '#angular/core';
import { trigger, state, style, transition, animate, AnimationBuilder, AnimationPlayer } from '#angular/animations';
export class Asset
{
constructor(public name:string,public description:string){};
}
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
assets:Asset[]=[];
cards=[];
private player: AnimationPlayer;
constructor(private animationBuilder:AnimationBuilder,
private elRef:ElementRef
){}
ngOnInit(){
this.setAssets();
this.setswitch();
}
setAssets(){
this.assets.push(new Asset("Asset1","Latest1"));
this.assets.push(new Asset("Asset2","Latest2"));
this.assets.push(new Asset("Asset3","Latest3"));
this.assets.push(new Asset("Asset4","Latest4"));
this.assets.push(new Asset("Asset5","Latest5"));
this.assets.push(new Asset("Asset6","Latest6"));
this.assets.push(new Asset("Asset7","Latest7"));
this.assets.push(new Asset("Asset8","Latest8"));
this.assets.push(new Asset("Asset9","Latest9"));
for(var i=0; i<this.assets.length;i++){
console.log(this.assets[i].name);
}
}
setswitch() {
for (let i = 0; i < this.assets.length; i++) {
let cardshow = {
id: i.toString(),
isShow : false
};
this.cards.push(cardshow);
}
console.log(this.cards);
}
animate(i){
this.cards[i].isShow=true;
let animationFactory;
animationFactory = this.animationBuilder
.build([
style({ width: '0' }),
animate(200, style({ width: 200 }))
]);
let elem:Element = document.getElementById("div"+(i));
console.log("Elament",elem);
console.log("INDEX",i);
this.player = animationFactory.create(elem);
this.player.play();
}
}
html:
<div>
<mat-grid-list cols="3" rowHeight="3:1">
<mat-grid-tile *ngFor="let asset of assets; index as i">
<div class="border">
<p>{{asset.name}} </p>
<p>{{asset.description}} </p>
<button (click)="animate(i)">click</button>
</div>
<div [ngClass]="!cards[i].isShow?'hide':''" id="{{'div'+i}}" class="border" >
<p>{{asset.description}} </p>
<button>click</button>
</div>
</mat-grid-tile>
</mat-grid-list>
</div>
css:
p {
font-family: Lato;
}
.border{
border:1px solid black;
padding-left: 20px;;
padding-right:20px;
}
.hide{
display:none;
}
EDIT: I need the other card to be completely hidden under the incoming card.Also after clicking on the button inside the incoming card, the animation should be undone(The card should retract back). Also what I'm doing now is increasing the width. What i expect is that the new card should come in from the left sort of like as we see in a drawer
check this stackblitz
app.component.css to be:
p {
font-family: Lato;
}
.border{
border:1px solid black;
padding-left: 20px;;
padding-right:20px;
background: #ffe6ea;
}
.hide{
display:none;
}
.borderPopUp{
padding-left: 20px;;
padding-right:20px;
position:absolute;
background:#d3d3d3d4;
animation: openLikeDrawer 800ms ease-in-out;
width:50%;
left:20%;
}
#keyframes openLikeDrawer{
from {left:0px; }
to { left: 20%; }
}
app.component.html to be :
<div>
<mat-grid-list cols="3" rowHeight="3:1">
<mat-grid-tile *ngFor="let asset of assets; index as i">
<div class="border">
<p>{{asset.name}} </p>
<p>{{asset.description}} </p>
<button (click)="asset.isShow = true">click</button>
</div>
<div *ngIf="asset.isShow" class="borderPopUp" >
<p>{{asset.description}} </p>
<button (click)='asset.isShow = false'>click</button>
</div>
</mat-grid-tile>
</mat-grid-list>
</div>
This is my final solution:
import { Component, OnInit } from '#angular/core';
import { LearningContentService } from '../../../service/learningcontent.service';
import { ActivatedRoute } from '#angular/router'
import { trigger, style, transition, animate, keyframes, query, stagger } from '#angular/animations';
export class Asset {
name: string;
description: string;
cardtoggle:boolean=false;
constructor(rawObj: any) {
this.name = rawObj.name;
this.description = rawObj.description;
this.cardtoggle = rawObj.cardtoggle;
}
}
#Component({
selector: 'app-catalogue',
templateUrl: './catalogue.component.html',
styleUrls: ['./catalogue.component.scss'],
animations: [
trigger('listAnimation', [
transition('* => *', [
query(':enter', style({ opacity: 0 }), { optional: true }),
query(':enter', stagger('50ms', [
animate('1s ease-in', keyframes([
style({ opacity: 0, transform: 'translateY(-75%)', offset: 0 }),
style({ opacity: .5, transform: 'translateY(35px)', offset: 0.3 }),
style({ opacity: 1, transform: 'translateY(0)', offset: 1.0 }),
]))]), { optional: true })
])
],
),
]
})
export class CatalogueComponent implements OnInit {
assets: Array<Asset> = [];
constructor(private route: ActivatedRoute,
private learningService: LearningContentService,
) {
}
ngOnInit() {
this.loadAssets();
}
loadAssets() {
this.learningService.assets().subscribe((res: any) => {
const datas: Array<any> = res;
datas.forEach(asset => this.assets.push(new Asset(asset)));
console.log(this.assets);
});
}
animate(asset) {
asset.cardtoggle = true;
}
close(asset) {
asset.cardtoggle = false;
}
}
html:
<div fxLayout="column">
<div fxLayout="row">
<p class="page-heading" fxFlex="80%">Catalogue</p>
<div class="page-content-filter" fxLayoutAlign="end">
<button mat-button class="search-btn"><i class="material-icons"> search </i></button>
<input class="form-filter" matInput placeholder="Search...">
</div>
</div>
<mat-grid-list gutterSize="20px" cols="3" rowHeight="3:1" [#listAnimation]="assets.length">
<mat-grid-tile *ngFor="let asset of assets">
<div class="full-width white">
<div class="padding20px" fxLayout="column" fxLayoutGap="15px">
<div fxLayout="row" fxLayoutGap="15px">
<img fxFlex="10" style="width:50px;height:50px;" src="../../../../assets/images/images.jpeg" mat-card-image>
<b fxFlex="100">{{asset.name}}</b>
<mat-icon fxLayoutAlign="end end" class="small-icon pointer" (click)="animate(asset)">spa</mat-icon>
</div>
<div fxLayout="row" fxLayoutGap="10px">
<mat-icon class="small-icon">person</mat-icon>
<p class="small-heading"> Mohit Harshan</p>
<mat-divider vertical="true"></mat-divider>
<mat-icon class="small-icon">play_arrow</mat-icon>
<p class="small-heading">Video</p>
<mat-divider vertical="true"></mat-divider>
<mat-icon class="small-icon">face</mat-icon>
<p class="small-heading">5 points</p>
</div>
<mat-progress-bar class="progress" mode="determinate" value="40"></mat-progress-bar>
</div>
</div>
<div class="pull-right" [ngClass]="{'show': asset.cardtoggle }" class="card2">
<div class="padding20px" fxLayout="column" fxLayoutGap="15px">
<div fxLayout="row" fxLayoutGap="15px">
<b fxFlex="100" class="small-heading">{{asset.name}}</b>
<mat-icon fxLayoutAlign="end end" class="small-icon pointer" (click)="close(asset)">clear</mat-icon>
</div>
<div fxLayout="row" fxLayoutGap="10px">
<p class="small">{{asset.description}}</p>
</div>
<div fxLayout="row" fxLayoutGap="10px" fxFLex="100" fxLayoutAlign="end end">
<button fxFLex="100" mat-button class="green-button" >View Details</button>
</div>
</div>
</div>
</mat-grid-tile>
</mat-grid-list>
</div>
css:
.card2{
position:absolute;
z-index: 20;
background: white;
padding-left: 0px;
padding-right:0px;
width:100%;
height:100%;
margin-left: 100%;
transition: margin-left .5s ease-in-out;
}
.show {
margin-left: 0%;
}
.green-button{
border:1px solid lightgreen;
border-radius: 10%;
font-size: 10px;
color:green;
}

maps are overlapping in view?

I have 2 components in my angular application each one having map to show from mapbox, one of the component is as shown below
Component
import { Component, OnInit } from '#angular/core';
import * as mapboxgl from 'mapbox-gl';
#Component({
selector: 'app-acs',
templateUrl: './acs.component.html',
styleUrls: ['./acs.component.css']
})
export class AcsComponent implements OnInit {
constructor() { }
ngOnInit() {
mapboxgl.accessToken = 'api-key';
let mapbx = new mapboxgl.Map({
container: 'mapbx',
style: 'styles',
zoom: 5,
center: [-80.118, 25.897]
});
}
}
component html
<div class="col-md-12 contentDiv">
<div class="row">
<h4 class="center subHeader">ACS</h4>
</div>
<div class="row">
<div class="mapArea">
<div id='map'></div>
</div>
</div>
</div>
and i have another component with similar code
global css
.contentDiv{
border: 1px solid #b1b0b0;
margin: 3px;
height: auto;
}
.subHeader{
border-bottom: 1px solid #b1b0b0;
margin: 2px 0px;
padding: 5px;
}
.region{
font-size: 16px;
}
.regionDropDown{
display: inline-block;
width: auto;
margin: 0px 10px;
}
.mapArea{
background: #e8e5e5;
margin: 10px;
height: 80vh;
}
#map {
width: auto;
height: inherit;
position: relative;
}
these maps are creating the canvas and if i make display:none of 1st canvas in chrome dev tools am able to see the hidden map.
how can i separately display 2 maps?
I believe you need to use different id:
<div class="col-md-12 contentDiv">
<div class="row">
<h4 class="center subHeader">ACS</h4>
</div>
<div class="row">
<div class="mapArea">
<div [id]="randomId"></div>
</div>
</div>
</div>
Generate random ID:
import { Component, OnInit } from '#angular/core';
import * as mapboxgl from 'mapbox-gl';
#Component({
selector: 'app-acs',
templateUrl: './acs.component.html',
styleUrls: ['./acs.component.css']
})
export class AcsComponent implements OnInit {
public randomId: string;
constructor() { }
ngOnInit() {
mapboxgl.accessToken = 'api-key';
this.randomId = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
setTimeout(() => {
let mapbx = new mapboxgl.Map({
container: this.randomId,
style: 'styles',
zoom: 5,
center: [-80.118, 25.897]
});
}, 0);
}
}
Hope this will help you.
Try to give different ids for you selectors
component 1
<div class="col-md-12 contentDiv">
....
<div id='mapa'></div>
....
</div>
component 2
<div class="col-md-12 contentDiv">
....
<div id='mapb'></div>
....
</div>
as well in global css
#mapa {
width: auto;
height: inherit;
position: relative;
}
#mapb {
width: auto;
height: inherit;
position: relative;
}
Hope it helps

angular 2 change position to fixed on scroll

I have a left sidebar with position fixed. what I want to achieve is that when I scroll like about 50 or 60 pixel the position of the left sidebar should be changed to fixed.
Left-sidebar.component.ts
import { Component } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'left-sidebar',
templateUrl: 'left-sidebar.html',
styleUrls: ['left-sidebar.scss']
})
export class LeftSideBarComponent {
}
left-sidebar.html
<div class="col-sm-2 left-nav">
</div>
css
.left-nav {
position: absolute;
background: #424242;
height: 100%;
overflow: auto;
padding: 0;
z-index: 1;
}
How to change position of left sidebar from absolute to fixed on scroll?
I suggest you make use of the #HostListner decorator to listen to the scroll event just like this:
import { Inject, HostListener } from "#angular/core";
import { DOCUMENT } from "#angular/platform-browser";
#Component({
moduleId: module.id,
selector: 'left-sidebar',
templateUrl: 'left-sidebar.html',
styleUrls: ['left-sidebar.scss']
})
export class LeftSideBarComponent {
public fixed: boolean = false;
constructor(#Inject(DOCUMENT) private doc: Document) {}
#HostListener("window:scroll", [])
onWindowScroll() {
let num = this.doc.body.scrollTop;
if ( num > 50 ) {
this.fixed = true;
}else if (this.fixed && num < 5) {
this.fixed = false;
}
}
add the .fixed css to your scss file then in your template, you do the following:
<div class="col-sm-2 left-nav" [class.fixed]="fixed">
</div>
I'm using Angular 4 and that solution didn't worked out for me, I tried a different aproach, because num was returning 0 on scroll. ¯_(ツ)_/¯.
I hope this will work out for you as well.
import { Inject, HostListener } from "#angular/core";
#HostListener("window:scroll", ['$event'])
onWindowScroll($event:any) {
let top = window.scrollY;
if (top > 30) {
this.fixed = true;
console.log(top);
} else if (this.fixed && top < 5) {
this.fixed = false;
console.log(top);
}
}
.fixed {
#extend .bg-white;
position: fixed;
top: 80px;
z-index: 999;
}
<div class="container" [class.fixed]="fixed">
<div class="row">
<div class="col-12">
<div ngbDropdown class="dropdown custom-dropdown">
<a class="dropdown-toggle" id="dropdownBasic1" ngbDropdownToggle>Toggle dropdown</a>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<a class="dropdown-item">Action - 1</a>
<a class="dropdown-item">Another Action</a>
<a class="dropdown-item">Something else is here</a>
</div>
</div>
</div>
</div>
</div>

reactjs animations - using CSS only transitions

Can some one point me to a simple example using CSS transitions no other libraries in reactjs to animate image from negative to positive right/left positions on component load?
Here is what you are looking for
.example-enter {
opacity: 0.01;
position: relative;
left: -100px
}
.example-enter.example-enter-active {
opacity: 1;
position: relative;
left: 0;
transition: all 1s ease-in;
}
Component
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [0],
counter: 0
};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd(){
const counter = this.state.counter + 1,
items = this.state.items.concat([counter]);
this.setState({
counter,items
})
}
render(){
const items = this.state.items.map(item => {
return <li className='example' key={item}>{item}</li>
})
return <ul className='container'>
<ReactCSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</ReactCSSTransitionGroup>
<hr/>
<button onClick={this.handleAdd}>New One</button>
</ul>
}
}
React.render(<Container />, document.getElementById('container'));
And also link to >> React Animation & worked fiddle
Thanks

Resources