Overview
ScreenPulse combines Angular Material components, Bootstrap grid system, and custom SCSS for a cohesive dark-themed UI. This guide covers the styling architecture and best practices.
Global Styles
Theme Configuration
The application uses a custom color scheme based on the Deep Purple & Amber Material theme:
@use '@angular/material' as mat ;
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css' ;
html , body {
height : 100 % ;
}
body {
margin : 0 ;
font-family : Roboto, "Helvetica Neue" , sans-serif ;
background-color : black ;
}
@import 'ngx-toastr/toastr' ;
@font-face {
font-family : Glegoo;
src : url ( ./assets/fonts/Glegoo-Regular.ttf ) format ( 'truetype' );
}
:root {
--custom-amber : #f5cf3d ;
--custom-amber-disabled : #f5d03d4d ;
--custom-error : red ;
}
The application uses a custom “Glegoo” font for branding elements and defines CSS custom properties for consistent theming.
Custom CSS Variables
Value : #f5cf3dUsage : Primary accent color for buttons, links, and interactive elements.screen {
color : var ( --custom-amber );
font-weight : bold ;
}
Value : #f5d03d4d (semi-transparent)Usage : Disabled state for interactive elements.mat-mdc-icon-button [ disabled ] .mat-mdc-paginator-icon {
fill : var ( --custom-amber-disabled ) !important ;
}
Value : redUsage : Error states and validation messages.mat-mdc-form-field.mat-accent.mat-form-field-invalid {
--mdc-outlined-text-field-outline-color : var ( --custom-error );
}
Angular Material Theming
Material Component Customization
ScreenPulse extensively customizes Material components to match the dark theme:
Paginator Styling
.mat-mdc-paginator {
background-color : #00000000 !important ;
border-radius : 20 px ;
border : 2 px solid var ( --custom-amber );
}
.mat-mdc-paginator-range-label {
color : var ( --custom-amber );
}
.mat-mdc-paginator-icon {
fill : var ( --custom-amber ) !important ;
}
Form Field Theming
.mat-mdc-form-field.mat-accent {
--mdc-outlined-text-field-outline-color : var ( --custom-amber );
--mdc-outlined-text-field-focus-outline-color : var ( --custom-amber );
--mdc-outlined-text-field-hover-outline-color : var ( --custom-amber );
}
.mat-mdc-form-field {
color : var ( --custom-amber );
padding : 10 px ;
}
Select Dropdown
:: ng-deep div .mat-mdc-select-panel {
background-color : rgb ( 0 , 0 , 0 ) !important ;
border-left : 1 px solid var ( --custom-amber );
border-right : 1 px solid var ( --custom-amber );
border-bottom : 1 px solid var ( --custom-amber );
}
:: ng-deep .mat-mdc-option:hover {
background-color : var ( --custom-amber ) !important ;
color : black !important ;
}
Use ::ng-deep (deprecated but functional) or global styles for deep component styling. Consider using ViewEncapsulation.None for component-specific global styles.
Bootstrap Grid System
Responsive Layouts
ScreenPulse uses ng-bootstrap for responsive grid layouts:
@media only screen and ( max-width : 600 px ) {
.button-links-container {
display : none ;
}
.login-container {
display : none ;
}
}
@media only screen and ( min-width : 601 px ){
.toogle-menu-button {
display : none ;
}
.expanded-menu-container {
display : none ;
}
}
search-bar.component.scss
@media only screen and ( max-width : 601 px ) {
form {
width : 100 % ;
}
}
@media only screen and ( min-width : 602 px ) and ( max-width : 992 px ) {
form {
width : 70 % ;
}
}
Component-Specific Styles
Navbar Component
The navbar demonstrates flexbox layouts and responsive design:
mat-toolbar {
height : 80 px ;
display : flex ;
flex-direction : column ;
background : #000000 ;
color : rgb ( 255 , 255 , 255 );
margin-left : auto ;
margin-right : auto ;
font-family : 'Glegoo' ;
}
.screen {
color : #F5CF3D ;
font-weight : bold ;
}
.spacer {
flex : 1 1 auto ;
}
.navbar-container {
display : flex ;
flex-direction : row ;
align-items : center ;
justify-content : space-around ;
width : 100 % ;
height : 100 % ;
}
Hover Effects with Transitions
Create smooth hover effects using CSS transitions:
.button-links-container a {
text-decoration : none ;
position : relative ;
color : white ;
}
.button-links-container a ::before {
content : '' ;
position : absolute ;
width : 100 % ;
height : 2 px ;
border-radius : 4 px ;
background-color : white ;
bottom : -4 px ;
left : 0 ;
transform-origin : right ;
transform : scaleX ( 0 );
transition : transform .3 s ease-in-out ;
}
.button-links-container a :hover::before {
transform-origin : left ;
transform : scaleX ( 1 );
}
This creates an elegant underline animation that grows from left to right on hover.
Favorites Card Component
Complex card layout with animations and responsive images:
favorites-card.component.scss
.favorite-card {
flex : 1 1 160 px ;
max-width : 200 px ;
margin : 0 ;
text-align : center ;
border-radius : 10 px ;
position : relative ;
border : 1 px solid rgba ( 255 , 255 , 255 , 0.247 );
background-color : #000000 ;
}
.img-container2 {
width : 115 px ;
height : 165 px ;
background-color : #0a0505 ;
border-radius : 10 px 10 px 0 0 ;
background-size : 100 % ;
background-position : center ;
transition : background-size 1 s ease , background-position 1 s ease ;
display : flex ;
justify-content : space-between ;
}
@media only screen and ( min-width : 801 px ) {
.img-container2:hover {
background-size : 120 % ;
background-position : center ;
cursor : pointer ;
}
}
Type-Based Styling
Different styles for movie types using classes:
favorites-card.component.scss
.chip {
width : 100 % ;
border-radius : 30 px ;
font-style : italic ;
font-weight : bold ;
color : white ;
text-align : center ;
box-shadow : rgba ( 0 , 0 , 0 , 0.4 ) 0 px 2 px 4 px ,
rgba ( 0 , 0 , 0 , 0.3 ) 0 px 7 px 13 px -3 px ,
rgba ( 0 , 0 , 0 , 0.2 ) 0 px -3 px 0 px inset ;
}
.movie .chip {
background-color : rgb ( 255 , 0 , 0 );
}
.series .chip {
background-color : rgb ( 255 , 255 , 0 );
}
.game .chip {
background-color : rgb ( 0 , 128 , 0 );
}
Animations
Keyframe Animations
Create custom animations for interactive elements:
favorites-card.component.scss
.edition {
position : absolute ;
bottom : 34 px ;
width : 100 % ;
animation-name : edition;
animation-duration : 1.2 s ;
animation-fill-mode : forwards ;
border-radius : 10 px ;
}
@keyframes edition {
0% {
bottom : 0 % ;
height : 100 px ;
}
100% {
bottom : 0 % ;
height : 160 px ;
visibility : visible ;
}
}
Transition Effects
Smooth transitions for hover states:
.img-container2 {
transition : background-size 1 s ease , background-position 1 s ease ;
}
.img-container2:hover {
background-size : 120 % ;
cursor : pointer ;
}
Box Shadows
Layered Shadow Effects
ScreenPulse uses layered box-shadows for depth:
box-shadow:
rgba(0, 0, 0, 0 .4 ) 0px 2px 4px, // Main shadow
rgba(0, 0, 0, 0 .3 ) 0px 7px 13px -3px, // Softer extended shadow
rgba(0, 0, 0, 0 .2 ) 0px -3px 0px inset; // Inner shadow for depth
Layer multiple shadows with different blur radii and offsets to create realistic depth and elevation effects.
Styled form with Material components:
search-bar.component.scss
form {
background-color : #000000 ;
width : 100 % ;
padding-top : 20 px ;
margin-left : auto ;
margin-right : auto ;
border-radius : 10 px ;
box-shadow : -10 px 0 px 13 px -7 px #000000 ,
10 px 0 px 13 px -7 px #000000 ,
inset 5 px 5 px 8 px 12 px rgba ( 0 , 0 , 0 , 0 );
display : flex ;
flex-direction : column ;
}
mat-label {
color : var ( --custom-amber ) !important ;
}
.mdc-text-field__input {
color : var ( --custom-amber ) !important ;
}
.button-container button [ disabled ] {
opacity : 1 ;
background-color : #683ab76e ;
}
.button-icon-disabled {
color : #202020 !important ;
}
.button-icon-enabled {
color : #ffffff !important ;
}
Loading Spinner
Minimalist loading indicator styling:
loading-spinner.component.scss
.loading-container {
text-align : center ;
color : #f5cf3d ;
}
.loading-text {
display : inline-flex ;
align-items : center ;
gap : 8 px ;
}
Best Practices
1. Use CSS Custom Properties
// ✅ Good - Reusable and themable
.button {
color : var ( --custom-amber );
}
// ❌ Bad - Hardcoded colors
.button {
color : #f5cf3d ;
}
2. Mobile-First Responsive Design
// ✅ Good - Mobile first
.container {
width : 100 % ;
}
@media only screen and ( min-width : 601 px ) {
.container {
width : 70 % ;
}
}
// ❌ Bad - Desktop first
.container {
width : 70 % ;
}
@media only screen and ( max-width : 600 px ) {
.container {
width : 100 % ;
}
}
3. Component-Scoped Styles
// Component-specific file: favorites-card.component.scss
.favorite-card {
// Styles scoped to this component
}
4. Consistent Spacing
button {
margin : 10 px ;
padding : 10 px ;
}
mat-toolbar {
height : 80 px ;
}
5. Accessible Color Contrast
Ensure text is readable against backgrounds:
.chip {
color : white ;
text-shadow :
1 px 1 px 0.5 px #000 ,
-1 px 1 px 0.5 px #000 ,
-1 px -1 px 0 #000 ,
1 px -1 px 0 #000 ;
}
Carousel Component Example
:host {
--carousel-btn-size : 50 px ;
--carousel-btn-bg : rgba ( 0 , 0 , 0 , 0.5 );
overflow : hidden ;
background : #ffff0000 ;
height : 80 % ;
margin-left : 20 px ;
border-radius : 10 px ;
display : flex ;
align-items : center ;
justify-content : center ;
flex-direction : column ;
}
img {
width : 70 % ;
height : auto ;
border-radius : 10 px ;
box-shadow : rgba ( 0 , 0 , 0 , 0.4 ) 0 px 2 px 4 px ,
rgba ( 0 , 0 , 0 , 0.3 ) 0 px 7 px 13 px -3 px ,
rgba ( 0 , 0 , 0 , 0.2 ) 0 px -3 px 0 px inset ;
cursor : pointer ;
}
@media only screen and ( min-width : 1367 px ) {
:host {
height : 100 % ;
}
}
Angular Material Official Angular Material documentation
Bootstrap Grid Bootstrap responsive grid system