x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<div class='mb-5'>
<div class='card p-4 rounded-4 border-0 bg-primary w-100 position-relative renuo-card'>
<div class='bg-primary rounded-4 z-index-0 position-absolute start-0 top-0 w-100 h-100 renuo-card-bg'></div>
<div class='row position-relative z-index-1'>
<div class='col-lg-8 d-flex flex-column'>
<div class="mb-3 gap-2 d-flex">
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Web Engineering</div>
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Strategy</div>
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Technology</div>
</div>
<div class='d-flex d-lg-none py-3'>
<img class="w-100 h-100 rounded-4 border-0" alt="Placeholder Image" src="/assets/example_image-106f60e51371bb8366a14732aaa0756199804e2754b5e983d6a5cce655d4446f.avif" />
</div>
<div class='card-body d-flex flex-column flex-grow-1 p-0'>
<h1 class='card-title text-white'>The Ultimate Guide to 4-Hour Intern Onboarding</h1>
<div class='row mt-auto'>
<div class='col-2 col-md-1 pe-0'>
<img class="rounded-2 w-75" alt="Placeholder Image" src="/assets/staff_portrait-fbdc00abaa1adcff140547d285e4a2cb38a023ad03a6eecb85d7e84d9ee70859.png" />
</div>
<div class='col mt-auto ps-0 ps-lg-1'>
<p class='card-text mb-0 text-white'>By <b>Pascal Andermatt</b></p>
<p class='card-text text-white'>2024-12-23</p>
</div>
<div class='col-auto mt-auto'>
<div class='bg-primary-subtle text-primary rounded-pill py-1 px-2'>
<i class='fa-solid fa-arrow-right button-arrow'></i>
</div>
</div>
</div>
</div>
</div>
<div class='col-lg-4 d-none d-lg-flex'>
<img class="w-100 rounded-4 border-0" alt="Placeholder Image" src="/assets/example_image-106f60e51371bb8366a14732aaa0756199804e2754b5e983d6a5cce655d4446f.avif" />
</div>
</div>
</div>
</div>
<div data-controller="card">
<div class="row mb-5">
<div class="col">
<div class='card bg-dark bg-opacity-75 rounded-4 image-card'
data-card-target="card"
data-action="mousemove->card#tiltEffect mouseleave->card#resetTiltEffect">
<div class='card-body text-white pb-4'>
<h6 class='card-subtitle mb-1 mt-1'>Guide</h6>
<p class='card-subtitle mb-2 text-white-50'>By Pascal</p>
<h4 class='card-title'>Intern onboarding</h4>
<img class="w-100 rounded-4 border-0" alt="Placeholder Image" src="/assets/example_image-106f60e51371bb8366a14732aaa0756199804e2754b5e983d6a5cce655d4446f.avif" />
</div>
</div>
</div>
<div class="col mt-5 mt-md-0">
<div class='card border-0 overlay-card'
data-card-target="card"
data-action="mousemove->card#tiltEffect mouseleave->card#resetTiltEffect">
<img class="w-100 h-100 object-fit-cover rounded-4 border-0" alt="Placeholder Image" src="/assets/example_image-106f60e51371bb8366a14732aaa0756199804e2754b5e983d6a5cce655d4446f.avif" />
<div class="card-img-overlay d-flex justify-content-center align-items-end">
<div class='d-flex flex-wrap justify-content-around card-body rounded-3 p-1 align-items-center blurred-background'>
<p class='card-subtitle text-white'>New blogs.</p>
<button type="button" class="rounded-3 text-white border-0 blurred-background-button px-2 text-nowrap">
Notify me
</button>
</div>
</div>
</div>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<div class='mb-5'>
<div class='card p-4 rounded-4 border-0 bg-primary w-100 position-relative renuo-card'>
<div class='bg-primary rounded-4 z-index-0 position-absolute start-0 top-0 w-100 h-100 renuo-card-bg'></div>
<div class='row position-relative z-index-1'>
<div class='col-lg-8 d-flex flex-column'>
<div class="mb-3 gap-2 d-flex">
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Web Engineering</div>
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Strategy</div>
<div class='bg-primary-subtle fw-bold text-primary rounded-pill px-2'>Technology</div>
</div>
<div class='d-flex d-lg-none py-3'>
<%= image_tag 'example_image.avif', class: 'w-100 h-100 rounded-4 border-0', alt: 'Placeholder Image' %>
</div>
<div class='card-body d-flex flex-column flex-grow-1 p-0'>
<h1 class='card-title text-white'>The Ultimate Guide to 4-Hour Intern Onboarding</h1>
<div class='row mt-auto'>
<div class='col-2 col-md-1 pe-0'>
<%= image_tag 'staff_portrait.png', class: 'rounded-2 w-75', alt: 'Placeholder Image' %>
</div>
<div class='col mt-auto ps-0 ps-lg-1'>
<p class='card-text mb-0 text-white'>By <b>Pascal Andermatt</b></p>
<p class='card-text text-white'><%= Time.zone.today %></p>
</div>
<div class='col-auto mt-auto'>
<div class='bg-primary-subtle text-primary rounded-pill py-1 px-2'>
<i class='fa-solid fa-arrow-right button-arrow'></i>
</div>
</div>
</div>
</div>
</div>
<div class='col-lg-4 d-none d-lg-flex'>
<%= image_tag 'example_image.avif', class: 'w-100 rounded-4 border-0', alt: 'Placeholder Image' %>
</div>
</div>
</div>
</div>
<div data-controller="card">
<div class="row mb-5">
<div class="col">
<div class='card bg-dark bg-opacity-75 rounded-4 image-card'
data-card-target="card"
data-action="mousemove->card#tiltEffect mouseleave->card#resetTiltEffect">
<div class='card-body text-white pb-4'>
<h6 class='card-subtitle mb-1 mt-1'>Guide</h6>
<p class='card-subtitle mb-2 text-white-50'>By Pascal</p>
<h4 class='card-title'>Intern onboarding</h4>
<%= image_tag 'example_image.avif', class: 'w-100 rounded-4 border-0', alt: 'Placeholder Image' %>
</div>
</div>
</div>
<div class="col mt-5 mt-md-0">
<div class='card border-0 overlay-card'
data-card-target="card"
data-action="mousemove->card#tiltEffect mouseleave->card#resetTiltEffect">
<%= image_tag 'example_image.avif',
class: 'w-100 h-100 object-fit-cover rounded-4 border-0',
alt: 'Placeholder Image' %>
<div class="card-img-overlay d-flex justify-content-center align-items-end">
<div class='d-flex flex-wrap justify-content-around card-body rounded-3 p-1 align-items-center blurred-background'>
<p class='card-subtitle text-white'>New blogs.</p>
<button type="button" class="rounded-3 text-white border-0 blurred-background-button px-2 text-nowrap">
Notify me
</button>
</div>
</div>
</div>
</div>
</div>
</div>

_card.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//renuo card
$blurred-color-1: rgba(0, 0, 0, .1);
$blurred-color-2: rgba(0, 0, 0, .3);
.renuo-card-bg {
transition: transform .3s ease;
}
.button-arrow {
transition: padding .3s ease;
}
.renuo-card:hover {
.button-arrow {
padding-left: .5rem;
padding-right: .5rem;
}
.renuo-card-bg {
transform: scale(1.025);
}
}
//image card
.image-card {
transition: .3s ease-in-out;
width: 18rem;
}
.image-card:hover {
transition: transform .1s ease;
}
.overlay-card {
height: 15rem;
transition: .3s ease-in-out;
width: 15rem;
}
.overlay-card:hover {
transition: transform .1s ease;
}
.blurred-background {
backdrop-filter: blur(5px);
background-color: $blurred-color-1;
}
.blurred-background-button {
background-color: $blurred-color-2;
}

card_controller.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['card'];
tiltEffect(event) {
const card = event.currentTarget;
const rect = card.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -10;
const rotateY = ((x - centerX) / centerX) * 10;
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
}
resetTiltEffect(event) {
const card = event.currentTarget;
card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';
}
}