In this activity, I will create an Angular application to display a list of recipe in a grid layout. The app will fetch the data from a service, display it using a component, and utilize CSS Grid and Flexbox for layout. We will also apply the BEM CSS architecture for clean and maintainable styles.
Recipe Model
Create a model for the recipe. This will structure the recipe data and ensure we have a consistent format for each recipe.
Create the file recipe.model.ts
:
export interface Recipe {
id: number;
title: string;
imageUrl: string;
}
This model will define the structure for each recipe object.
Recipe Service
Next, we create a service to manage the list of recipe. We will add a few recipe to this service with placeholder data, including recipe images.
Create the service recipe.service.ts
:
import { Injectable } from '@angular/core';
import { Recipe } from './recipe.model';
@Injectable({
providedIn: 'root',
})
export class RecipeService {
getRecipes(): Recipe[] {
return [
{
id: 1,
title: 'Pancakes',
imageUrl: 'images/recipe.jpg',
},
{
id: 2,
title: 'Waffles',
imageUrl: 'images/recipe.jpg',
},
{
id: 3,
title: 'Omelette',
imageUrl: 'images/recipe.jpg',
},
{
id: 4,
title: 'Spaghetti Carbonara',
imageUrl: 'images/recipe.jpg',
},
{
id: 5,
title: 'Caesar Salad',
imageUrl:'images/recipe.jpg',
},
{
id: 6,
title: 'Grilled Cheese Sandwich',
imageUrl:'images/recipe.jpg',
},
{
id: 7,
title: 'Beef Stroganoff',
imageUrl: 'images/recipe.jpg',
},
{
id: 8,
title: 'Chicken Curry',
imageUrl: 'images/recipe.jpg',
},
{
id: 9,
title: 'Chocolate Brownies',
imageUrl: 'images/recipe.jpg',
},
{
id: 10,
title: 'Tacos',
imageUrl: 'images/recipe.jpg',
},
];
}
}
This service provides a list of recipe.
Displaying the recipe in the Component
Now, let’s fetch and display the book data in the recipe.component.ts
file. We'll also use CSS Grid and Flexbox for layout.
Create the component recipe.component.ts
:
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RecipeService } from './recipe.service';
import { Recipe } from './recipe.model';
@Component({
selector: 'app-recipe',
standalone: true,
templateUrl: './recipe.component.html',
styleUrls: ['./recipe.component.css'],
imports: [CommonModule],
})
export class RecipeComponent implements OnInit {
recipes: Recipe[] = [];
constructor(private recipeService: RecipeService) {}
ngOnInit(): void {
this.recipes = this.recipeService.getRecipes();
}
}
This component fetches the list of recipe from the RecipeService
and stores them in the recipe array.
Creating the Recipe Layout Using Grid and Flex
In the recipe.component.html
, we will display the recipe in a grid layout with individual book cards. We’ll use Flexbox for aligning the content inside the book card, and CSS Grid for the overall layout.
Create the HTML file recipe.component.html
:
<div class="recipe-grid">
<div class="recipe-card" *ngFor="let recipe of recipes">
<img class="recipe-card__image" [src]="recipe.imageUrl" [alt]="recipe.title" />
<h3 class="recipe-card__title">{{ recipe.title }}</h3>
<div class="recipe-card__buttons">
<button class="btn btn-primary">Ingredients</button>
<button class="btn btn-secondary">Trending!</button>
</div>
</div>
</div>
Styling the Recipe Cards Using BEM CSS Architecture
Create the CSS for the grid layout and styling the recipe cards. We’ll apply BEM CSS architecture for maintainability and clarity.
Create the CSS file recipe.component.css
:
.recipe-grid {
display: grid;
gap: 20px;
grid-template-columns: repeat(2, 1fr); /* 2 columns mobile */
padding: 20px;
}
@media (min-width: 768px) {
.recipe-grid {
grid-template-columns: repeat(3, 1fr); /* 3 columns tablets */
}
}
@media (min-width: 1024px) {
.recipe-grid {
grid-template-columns: repeat(5, 1fr); /* 5 columns desktops */
}
}
.recipe-card {
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 10px;
text-align: center;
display: flex;
flex-direction: column;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.recipe-card__image {
width: 100%;
height: 180px;
object-fit: cover;
border-radius: 4px;
margin-bottom: 10px;
}
.recipe-card__title {
font-size: 1.2rem;
margin: 10px 0;
font-weight: bold;
color: #333;
}
.recipe-card__buttons {
display: flex;
justify-content: space-around;
margin-top: auto;
}
.btn {
padding: 8px 12px;
font-size: 0.9rem;
border: none;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
}
.btn-secondary {
background-color: #28a745;
color: white;
}
.btn-secondary:hover {
background-color: #1e7e34;
}
The
.recipe-container
uses CSS Grid for the overall layout.Each
.recipe-card
uses Flexbox for the inner layout.BEM CSS is used for naming conventions to maintain modularity and clarity.
2 columns for mobile, 3 columns for tablets, and 5 columns for desktops
GitHub Link: https://github.com/RodelDecio/AngularRecipeGrid.git
Hosting URL: https://angularrecipegrid-54404.web.app