iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

目標

今天要完成的目標是:製作單曲展示區。
結構格式和「專輯展示區」一樣,但不同的是:

  • 專輯展示區 → 點擊後顯示歌曲清單
  • 單曲展示區 → 點擊後會直接跳轉到該單曲的歌詞頁面

今天先完成首頁的單曲展示區,明天會繼續完成單曲歌詞頁面。


HTML

<!-- 單曲展示區 -->
            <div class="single-section">
                <h2>Single</h2>
           
                <div class="single-carousel-container">
                    <!-- 左箭頭 -->
                    <button class="carousel-btn left" id="singlePrevBtn">‹</button>
           
                    <!-- 卡片區域 -->
                    <div class="single-carousel-track" id="singleCarouselTrack">
                        <a href="lyrics.html?song=song1" class="single-card">
                            <img src="images/WANTCHU.png" alt="Single 1">
                            <div class="overlay">
                                <h3>WANTCHU</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song2" class="single-card">
                            <img src="images/Beside you.jpg" alt="Single 2">
                            <div class="overlay">
                                <h3>beside you</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song3" class="single-card">
                            <img src="images/onoffonoff.jpg" alt="Single 3">
                            <div class="overlay">
                                <h3>onoffonoff</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song4" class="single-card">
                            <img src="images/just friends.jpg" alt="Single 4">
                            <div class="overlay">
                                <h3>just friends</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song5" class="single-card">
                            <img src="images/magnolia.jpg" alt="Single 5">
                            <div class="overlay">
                                <h3>magnolia</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song6" class="single-card">
                            <img src="images/as long as it takes you.jpg" alt="Single 6">
                            <div class="overlay">
                                <h3>as long as it takes you</h3>
                            </div>
                        </a>
                        <a href="lyrics.html?song=song7" class="single-card">
                            <img src="images/over u.jpg" alt="Single 7">
                            <div class="overlay">
                                <h3>over u</h3>
                            </div>
                        </a>
                    </div>
           
                    <!-- 右箭頭 -->
                    <button class="carousel-btn right" id="singleNextBtn">›</button>
                </div>
            </div>

說明:

  • .single-section → 整個單曲展示區的容器。
  • .single-carousel-container → 包住所有卡片與左右箭頭。
  • .single-carousel-track → 橫向排列的卡片軌道,裡面放多張 .single-card。
  • .single-card → 單曲卡片,包含圖片和一層 .overlay 遮罩。
  • href="lyrics.html?song=song1" → 點擊卡片後會跳到 lyrics.html,並透過 URL 參數傳遞是哪首歌,方便後續動態載入歌詞。

CSS

/* 單曲展示區 */
.single-section {
    text-align: center;
    padding: 40px 20px;
    background: linear-gradient(135deg, #2c2c2c 0%, #1a1a2e 100%);
    color: white;
}


.single-section h2 {
    font-size: 2.5em;
    margin-bottom: 30px;
    text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}


/* 輪播容器 */
.single-carousel-container {
    position: relative;
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    overflow: hidden;
}


/* 輪播軌道 */
.single-carousel-track {
    display: flex;
    gap: 16px;
    transition: transform 0.5s ease-out;
}


/* 單曲卡片 */
.single-card {
    position: relative;
    flex: 0 0 auto;
    width: 220px;
    height: 220px;
    overflow: hidden;
    border-radius: 12px;
}


.single-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.3s ease;
}


.single-card:hover img {
    transform: scale(1.05);
}


/* 遮罩效果 */
.single-card .overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(218, 216, 216, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s ease;
}


.single-card:hover .overlay {
    opacity: 1;
}


/* 遮罩文字 */
.single-card .overlay h3 {
    font-size: 20px;
    font-weight: bold;
    color: rgb(0, 0, 0);
    text-align: center;
    padding: 0 10px;
}


/* 左右箭頭 */
.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(255, 255, 255, 0.95);
    border: none;
    border-radius: 50%;
    font-size: 24px;
    cursor: pointer;
    width: 55px;
    height: 55px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);
    transition: all 0.3s ease;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #333;
    font-weight: bold;
}


.carousel-btn:hover {
    background: white;
    transform: translateY(-50%) scale(1.1);
    box-shadow: 0 6px 20px rgba(0,0,0,0.3);
}


.carousel-btn:active {
    transform: translateY(-50%) scale(0.95);
}


.carousel-btn.left {
    left: 10px;
}


.carousel-btn.right {
    right: 10px;
}


/* 禁用狀態 */
.carousel-btn:disabled {
    opacity: 0.3;
    transform: translateY(-50%) scale(0.9);
}


.carousel-btn:disabled:hover {
    transform: translateY(-50%) scale(0.9);
    background: rgba(255, 255, 255, 0.95);
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}


/* 響應式設計 */
@media (max-width: 768px) {
    .single-card {
        width: 180px;
        height: 180px;
        margin-right: 10px;
    }
   
    .carousel-btn {
        width: 45px;
        height: 45px;
        font-size: 20px;
    }
}


@media (max-width: 480px) {
    .single-card {
        width: 160px;
        height: 160px;
        margin-right: 8px;
    }
}

說明

  • .single-section → 使用漸層背景,讓單曲區塊和其他區域有區隔感。
  • .single-card → 固定寬高的卡片,圖片採 object-fit: cover,確保不變形。
  • .overlay → hover 時才會浮現,呈現出歌曲名稱。
  • .carousel-btn → 左右箭頭有 hover 與 active 的縮放效果,更有互動感。
  • 響應式設計 → 在平板、手機上自動縮小卡片與按鈕。

Javascript

套用之前寫的通用函式

// 單曲展示區
createCarousel({
    trackId: 'singleCarouselTrack',
    prevBtnId: 'singlePrevBtn',
    nextBtnId: 'singleNextBtn',
    cardSelector: '.single-card',
    gap: 16
});

說明

  • 我沿用之前寫好的 createCarousel 通用函式。
  • 傳入不同的參數(trackId、按鈕 Id、卡片選擇器…),就能快速建立一個新的輪播區。
  • 這樣寫的好處 → 專輯展示區和單曲展示區可以共用同一套程式碼,減少重複。

畫面展示

https://ithelp.ithome.com.tw/upload/images/20251002/20168364hoLINMzu9p.png

https://ithelp.ithome.com.tw/upload/images/20251002/20168364u89pV7O6Zi.png


今天的成果

  • 完成了 單曲展示區的首頁版面
  • 每張卡片都有圖片與 hover 效果
  • 點擊卡片會跳轉到 lyrics.html,並附帶歌曲參數
  • 左右箭頭能切換多首單曲,支援響應式設計

上一篇
修正專輯展示區及MV展示區的滑動效果
下一篇
製作單曲歌詞頁面
系列文
打造專屬於歌手的音樂資訊網頁:從零開始的前端實作與技術分享19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言