Features Implemented:
Responsive 4-Column Layout:
- Uses CSS Grid for desktop view (4 columns)
- Switches to 2 columns on medium screens (tablets)
- Stacks to 1 column on mobile devices
Profile Column:
- Circular profile image with border
- Centered with caption
- Soft shadow and hover effect
Basic Details Column:
- Student name as heading
- Field of study as subheading
- Short bio paragraph
Portfolio Column:
- List of 5 projects with clickable links
- Hover effects for better interactivity
Contact Column:
- Contact form with name, email, and message fields
- JavaScript alert on form submission
- Download CV button with distinct styling
Design Elements:
- Clean, minimal aesthetic
- Soft shadows and rounded corners
- Hover animations for interactivity
- Professional color scheme
- Legible typography
Technical Implementation:
- Pure HTML, CSS, and JavaScript (no external libraries)
- CSS Grid for layout
- Media queries for responsiveness
- Simple form validation and feedback
The placeholder image can be replaced with an actual student photo by changing the src attribute in the profile image tag. Similarly, the download CV link can be updated to point to an actual PDF file.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.slider-container {
max-width: 1000px;
width: 100%;
position: relative;
overflow: hidden;
border-radius: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.slider {
display: flex;
transition: transform 0.5s ease-in-out;
height: 500px;
}
@media (max-width: 768px) {
.slider {
height: 400px;
}
}
@media (max-width: 480px) {
.slider {
height: 300px;
}
}
.slide {
min-width: 100%;
position: relative;
}
.slide img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.slide-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
color: white;
padding: 30px;
text-align: center;
}
.slide h2 {
margin-bottom: 10px;
font-size: 2rem;
}
.slide p {
font-size: 1rem;
opacity: 0.9;
}
.slider-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.7);
color: #333;
border: none;
width: 50px;
height: 50px;
border-radius: 50%;
font-size: 1.5rem;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease;
z-index: 10;
}
.slider-btn:hover {
background: rgba(255, 255, 255, 0.9);
}
#prevBtn {
left: 20px;
}
#nextBtn {
right: 20px;
}
.pagination {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 10;
}
.pagination-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
cursor: pointer;
transition: all 0.3s ease;
}
.pagination-dot.active {
background: rgba(255, 255, 255, 0.9);
transform: scale(1.2);
}
/* Animation classes */
.fade {
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.fade.active {
opacity: 1;
}
.slide-left {
transform: translateX(-100%);
}
.slide-right {
transform: translateX(100%);
}
.zoom-in {
transform: scale(0.8);
opacity: 0;
transition: all 0.5s ease-in-out;
}
.zoom-in.active {
transform: scale(1);
opacity: 1;
}
document.addEventListener('DOMContentLoaded', function() {
const slider = document.getElementById('slider');
const slides = document.querySelectorAll('.slide');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const pagination = document.getElementById('pagination');
let currentSlide = 0;
let slideInterval;
const slideDuration = 5000; // 5 seconds
// Create pagination dots
slides.forEach((_, index) => {
const dot = document.createElement('div');
dot.classList.add('pagination-dot');
if (index === 0) dot.classList.add('active');
dot.addEventListener('click', () => goToSlide(index));
pagination.appendChild(dot);
});
const dots = document.querySelectorAll('.pagination-dot');
// Set initial slide positions
function initSlider() {
slides.forEach((slide, index) => {
if (index !== currentSlide) {
slide.style.display = 'none';
} else {
slide.style.display = 'block';
}
});
}
// Go to specific slide
function goToSlide(index, direction = null) {
// If clicking on current slide dot, do nothing
if (index === currentSlide) return;
const currentActive = slides[currentSlide];
const nextActive = slides[index];
// Reset all animations
slides.forEach(slide => {
slide.classList.remove('fade', 'slide-left', 'slide-right', 'zoom-in', 'active');
});
// Apply animation based on direction
if (direction === 'next') {
currentActive.classList.add('slide-left');
nextActive.style.display = 'block';
nextActive.classList.add('slide-right', 'active');
setTimeout(() => {
currentActive.style.display = 'none';
nextActive.classList.remove('slide-right');
}, 500);
} else if (direction === 'prev') {
currentActive.classList.add('slide-right');
nextActive.style.display = 'block';
nextActive.classList.add('slide-left', 'active');
setTimeout(() => {
currentActive.style.display = 'none';
nextActive.classList.remove('slide-left');
}, 500);
} else {
// Default fade animation when clicking dots
currentActive.classList.add('fade');
nextActive.style.display = 'block';
nextActive.classList.add('fade', 'active');
setTimeout(() => {
currentActive.style.display = 'none';
}, 500);
}
// Update current slide and pagination
currentSlide = index;
updatePagination();
// Reset auto-slide timer
resetInterval();
}
// Update pagination dots
function updatePagination() {
dots.forEach((dot, index) => {
dot.classList.toggle('active', index === currentSlide);
});
}
// Next slide
function nextSlide() {
const nextIndex = (currentSlide + 1) % slides.length;
goToSlide(nextIndex, 'next');
}
// Previous slide
function prevSlide() {
const prevIndex = (currentSlide - 1 + slides.length) % slides.length;
goToSlide(prevIndex, 'prev');
}
// Auto slide
function startInterval() {
slideInterval = setInterval(nextSlide, slideDuration);
}
function resetInterval() {
clearInterval(slideInterval);
startInterval();
}
// Event listeners
nextBtn.addEventListener('click', nextSlide);
prevBtn.addEventListener('click', prevSlide);
// Pause on hover
slider.addEventListener('mouseenter', () => {
clearInterval(slideInterval);
});
slider.addEventListener('mouseleave', startInterval);
// Touch support for mobile
let touchStartX = 0;
let touchEndX = 0;
slider.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
clearInterval(slideInterval);
}, {passive: true});
slider.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
startInterval();
}, {passive: true});
function handleSwipe() {
const threshold = 50;
if (touchEndX < touchStartX - threshold) {
nextSlide(); // Swipe left
} else if (touchEndX > touchStartX + threshold) {
prevSlide(); // Swipe right
}
}
// Initialize
initSlider();
startInterval();
// Lazy loading with IntersectionObserver
if ('IntersectionObserver' in window) {
const lazyImageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const lazyImage = entry.target;
if (lazyImage.dataset.src) {
lazyImage.src = lazyImage.dataset.src;
lazyImage.removeAttribute('data-src');
}
lazyImageObserver.unobserve(lazyImage);
}
});
});
// Observe all images (you would need to modify the HTML to use data-src)
document.querySelectorAll('img[data-src]').forEach(img => {
lazyImageObserver.observe(img);
});
}
});
Post a Comment
Thank you
Learning robo team