This is a submission for [Frontend Challenge v24.04.17]((https://dev.to/challenges/frontend-2024-05-29), Glam Up My Markup: Beaches
What I Built
I built an interactive webpage showcasing the best beaches in the world. The page includes a slider with beautiful images of each beach, descriptions, and a button to view the beach's location on a map. My goal was to create an engaging and visually appealing way to explore stunning beach destinations, providing users with both visual and informational content.
Demo
Here's the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Best Beaches in the World</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Roboto', sans-serif;
margin: 0;
padding: 0;
background: #f0f8ff;
color: #333;
}
header {
background: #48cae4;
color: #fff;
padding: 20px 0;
text-align: center;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
main {
max-width: 1200px;
margin: 20px auto;
padding: 0 20px;
}
h1, h2 {
margin: 0 0 20px;
}
h1 {
font-size: 2.5em;
}
h2 {
color: #0077b6;
font-size: 2em;
}
section {
margin-bottom: 40px;
}
ul {
list-style: none;
padding: 0;
}
li {
background: #ffffff;
margin: 20px 0;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s;
}
li:hover {
transform: translateY(-10px);
}
h3 {
margin: 0 0 10px;
color: #023e8a;
}
p {
margin: 0;
}
.slider {
position: relative;
max-width: 100%;
margin: auto;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.slides {
display: flex;
transition: transform 0.5s ease-in-out;
will-change: transform;
}
.slides img {
width: 100%;
border-radius: 10px;
pointer-events: none;
user-select: none;
}
.prev, .next {
position: absolute;
top: 50%;
transform: translateY(-50%);
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
border-radius: 5px;
}
.prev {
left: 10px;
}
.next {
right: 10px;
}
.dots {
text-align: center;
margin-top: 10px;
}
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}
.active, .dot:hover {
background-color: #717171;
}
button {
background-color: #48cae4;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-top: 10px;
cursor: pointer;
border-radius: 5px;
}
button:hover {
background-color: #0077b6;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.4);
padding-top: 60px;
}
.modal-content {
background-color: #fefefe;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 600px;
border-radius: 10px;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
#map {
height: 400px;
width: 100%;
border-radius: 10px;
}
</style>
</head>
<body>
<header>
<h1>Best Beaches in the World</h1>
</header>
<main>
<section>
<h2>Take me to the beach!</h2>
<p>Welcome to our curated list of the best beaches in the world. Whether you're looking for serene white sands, crystal-clear waters, or breathtaking scenery, these beaches offer a little something for everyone. Explore our top picks and discover the beauty that awaits you.</p>
</section>
<section>
<h2>Top Beaches</h2>
<div class="slider" id="slider">
<div class="slides" id="slides">
<!-- Images will be added here by JavaScript -->
</div>
<button class="prev" id="prevBtn">❮</button>
<button class="next" id="nextBtn">❯</button>
</div>
<div class="dots" id="dots"></div>
<ul id="beachList">
<!-- Beach details will be added here by JavaScript -->
</ul>
</section>
</main>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<div id="map"></div>
</div>
</div>
<script>
const accessKey = 'YOUR_ACCESS_KEY';
const beaches = [
{
name: 'Whitehaven Beach, Australia',
description: 'Located on Whitsunday Island, Whitehaven Beach is famous for its stunning white silica sand and turquoise waters. It\'s a perfect spot for swimming, sunbathing, and enjoying the natural beauty of the Great Barrier Reef.',
searchTerm: 'Whitehaven Beach',
lat: -20.282,
lng: 149.037
},
{
name: 'Grace Bay, Turks and Caicos',
description: 'Grace Bay is known for its calm, clear waters and powdery white sand. This beach is ideal for snorkeling, diving, and enjoying luxury resorts that line its shore.',
searchTerm: 'Grace Bay',
lat: 21.795,
lng: -72.172
},
{
name: 'Baia do Sancho, Brazil',
description: 'Baia do Sancho, located on Fernando de Noronha island, offers stunning cliffs, vibrant marine life, and crystal-clear waters, making it a paradise for divers and nature lovers.',
searchTerm: 'Baia do Sancho',
lat: -3.857,
lng: -32.416
},
{
name: 'Navagio Beach, Greece',
description: 'Also known as Shipwreck Beach, Navagio Beach is famous for the rusting shipwreck that rests on its sands. Accessible only by boat, this secluded cove is surrounded by towering cliffs and azure waters.',
searchTerm: 'Navagio Beach',
lat: 37.859,
lng: 20.624
},
{
name: 'Playa Paraiso, Mexico',
description: 'Playa Paraiso, located in Tulum, offers pristine white sands and turquoise waters against the backdrop of ancient Mayan ruins. It\'s a perfect blend of history and natural beauty.',
searchTerm: 'Playa Paraiso',
lat: 20.216,
lng: -87.431
},
{
name: 'Anse Source d\'Argent, Seychelles',
description: 'Anse Source d\'Argent is renowned for its unique granite boulders, shallow clear waters, and soft white sand. This beach is perfect for photography, snorkeling, and relaxation.',
searchTerm: 'Anse Source d\'Argent',
lat: -4.373,
lng: 55.826
},
{
name : 'Seven Mile Beach, Cayman Islands',
description: 'Stretching for seven miles, this beach offers soft coral sand, clear waters, and numerous activities such as snorkeling, paddleboarding, and beachcombing.',
searchTerm: 'Seven Mile Beach',
lat: 19.313,
lng: -81.213
}
];
let currentSlide = 0;
async function fetchImageUrl(searchTerm) {
const response = await fetch(`https://api.unsplash.com/search/photos?page=1&query=${encodeURIComponent(searchTerm)}&client_id=${accessKey}`);
const data = await response.json();
if (data.results && data.results.length > 0) {
return `${data.results[0].urls.raw}&w=1600`;
} else {
return 'https://via.placeholder.com/1600x900?text=Image+Not+Available';
}
}
async function showSlides() {
const slidesContainer = document.getElementById('slides');
slidesContainer.innerHTML = '';
const dotsContainer = document.getElementById('dots');
dotsContainer.innerHTML = '';
const beach = beaches[currentSlide];
const slide = document.createElement('div');
slide.classList.add('mySlides');
const img = document.createElement('img');
img.src = await fetchImageUrl(beach.searchTerm);
slide.appendChild(img);
slidesContainer.appendChild(slide);
beaches.forEach((_, index) => {
const dot = document.createElement('span');
dot.classList.add('dot');
dot.setAttribute('onclick', `currentSlide = ${index}; showSlides();`);
if (index === currentSlide) {
dot.classList.add('active');
}
dotsContainer.appendChild(dot);
});
const beachList = document.getElementById('beachList');
beachList.innerHTML = '';
const li = document.createElement('li');
li.innerHTML = `
<h3>${beach.name}</h3>
<p>${beach.description}</p>
<button onclick="openMap(${currentSlide})">View on Map</button>
`;
beachList.appendChild(li);
}
function changeSlide(n) {
currentSlide = (currentSlide + n + beaches.length) % beaches.length;
showSlides();
}
function openMap(index) {
const beach = beaches[index];
const modal = document.getElementById('myModal');
const modalContent = document.querySelector('.modal-content');
modalContent.innerHTML = `
<span class="close" onclick="closeMap()">×</span>
<div id="map"></div>
`;
modal.style.display = 'block';
initMap(beach.lat, beach.lng);
}
function closeMap() {
const modal = document.getElementById('myModal');
modal.style.display = 'none';
}
async function initMap(lat, lng) {
const { Map } = await google.maps.importLibrary("maps");
const mapOptions = {
center: { lat: parseFloat(lat), lng: parseFloat(lng) },
zoom: 12
};
const map = new Map(document.getElementById('map'), mapOptions);
const marker = new google.maps.Marker({
position: { lat: parseFloat(lat), lng: parseFloat(lng) },
map: map,
title: 'Beach Location'
});
}
window.onload = function() {
showSlides();
};
document.getElementById('prevBtn').addEventListener('click', () => {
changeSlide(-1);
document.getElementById('slider').scrollIntoView({ behavior: 'smooth' });
});
document.getElementById('nextBtn').addEventListener('click', () => {
changeSlide(1);
document.getElementById('slider').scrollIntoView({ behavior: 'smooth' });
});
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" ></script>
</body>
</html>
Journey
The process of building this project involved several key steps:
Design and Layout: I focused on creating a clean, responsive design that highlights the beauty of each beach. The use of Google Fonts and CSS styling helped achieve a modern look.
Image Fetching with Unsplash API: I learned how to fetch high-quality images dynamically from the Unsplash API based on search terms, ensuring that each beach image is relevant and visually appealing.
Slider Functionality: Implementing the slider required careful handling of image loading, transitions, and navigation controls to provide a smooth user experience.
Interactive Map: Integrating Google Maps API allowed users to view the exact location of each beach, adding an interactive element to the site.
Future Plans:
User Reviews: Integrate a section for user reviews and ratings to provide more insights and personal experiences.
Weather Information: Include real-time weather information for each beach to help users plan their visits better.
Top comments (1)
🙌