CSS로 이미지 슬라이드 만들기 - 3. 입체 3D 효과

슬라이드의 기본 구조와 구현 방법은 

-> CSS로 이미지 슬라이드 만들기 - 1. 투명 전환 효과

와 동일하고, 슬라이드를 전환하는 애니메이션 효과만 다르게 구현한 것입니다.

기본적인 슬라이드의 구조와 레이아웃을 만드는 자세한 방법은 첫 번째 슬라이드 만들기를 참고하시기 바랍니다.

완성된 이미지 슬라이드 소스는 다음 다운로드 링크에서 다운로드 받을 수 있습니다.

slider3.zip0.22MB

만들게 되는 슬라이드는 3D 입체 모양으로 슬라이드들이 약간씩 겹쳐서 보이고, 선택된 슬라이드가 맨 앞으로 나오고 나머지 슬라이드들은 순차적으로 멀어져 보이도록 이동하는 입체 애니메이션으로 구현됩니다.

현재 선택된 슬라이드를 제외한 나머지 슬라이드들은 순차적으로 멀어지는 효과를 주기 위해 여러 단계의 CSS를 슬라이드마다 부여해야 합니다.

반복되는 작업들을 CSS로 모두 구현해야 하기 때문에 CSS 작성량이 다소 많은 편이며, SASS나 LESS와 같은 프리프로세서를 사용해서 코딩하면 반복되는 CSS 작성량을 상당 부분 줄일 수도 있습니다.

먼저 HTML 코드를 확인하겠습니다.

라디오박스로 슬라이드 이동을 구현하며, 실제 클릭 이동 구현은 슬라이드 하단의 라벨 태그로 만든 불릿(Bullets)으로 구현합니다.

<div class="slider">
    <input type="radio" name="slide" id="slide1" checked>
    <input type="radio" name="slide" id="slide2">
    <input type="radio" name="slide" id="slide3">
    <input type="radio" name="slide" id="slide4">
    <ul id="imgholder" class="imgs">
        <li><img src="./backup/816/img/slide1.jpg"></li>
        <li><img src="./backup/816/img/slide2.jpg"></li>
        <li><img src="./backup/816/img/slide3.jpg"></li>
        <li><img src="./backup/816/img/slide4.jpg"></li>
    </ul>
    <div class="bullets">
        <label for="slide1">&nbsp;</label>
        <label for="slide2">&nbsp;</label>
        <label for="slide3">&nbsp;</label>
        <label for="slide4">&nbsp;</label>
    </div>
</div>

CSS로 슬라이드의 기본 구조를 만들어보겠습니다.

슬라이드 이미지 크기는 640x480px 입니다. 슬라이드 이미지 크기에 맞춰 슬라이드 기본 크기를 정의합니다.

640x480px 크기의 슬라이드를 가운데 정렬("margin: 0 auto;")하고 슬라이드 영역 바깥에 위치한 요소들은 보이지 않도록 해서("overflow: hidden;") 현재 슬라이드 오른쪽에 위치한 나머지 슬라이드들이 보이지 않도록 합니다.

불릿을 클릭하는데 따라 오른쪽의 안보이는 위치에 있던 슬라이드가 외쪽으로 이동하면서 표시되는 구조입니다.

.slider{
    width: 640px;
    height: 480px;
    position: relative;
    margin: 0 auto;
}
.slider input[type=radio]{
    display: none;
}

슬라이드 이미지 목록을 배치합니다.

기본적으로 슬라이드 영역 크기 오른쪽 바깥에 위치를 시킵니다.

슬라이드를 조금 더 보기좋게 하기 위해 테두리를 30px씩 둥글게 깍아서 입체적인 효과가 조금 더 두드러지도록 했습니다.

슬라이드 배치는 여기서는 별도로 하지 않습니다. 개별 슬라이드를 입체적으로 보이도록 크기와 위치를 나중에 별도로 지정하기 때문에 여기서는 기본적인 슬라이드 모양만 정의하면 됩니다.

ul.imgs{
    padding: 0;
    margin: 0;
}
ul.imgs li{
    position: absolute;
    list-style: none;
    padding: 0;
    margin: 0;
    border-radius: 30px;
}
ul.imgs li img{
    border-radius: 30px;
    border: 5px solid rgba(0,0,0,0.3);
}

불릿은 라디오박스와 조합된 라벨("<label>") 태그로 만듭니다.

라이오박스는 보이지 않지만, 라벨 태그를 클릭하면 라디오박스를 클릭해 선택한 것과 동일한 이벤트가 발생하기 때문에, 라벨을 슬라이드 이동 불릿으로 만들어서 슬라이드 가운데 하단에 배치를 합니다.

.bullets{
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 20px;
    z-index: 2;
}
.bullets label{
    display: inline-block;
    border-radius: 50%;
    background-color: rgba(0,0,0,0.55);
    width: 20px;
    height: 20px;
    cursor: pointer;
}
/* 현재 선택된 불릿 배경 흰색으로 구분 표시 */
.slider input[type=radio]:nth-child(1):checked~.bullets>label:nth-child(1){
    background-color: #fff;
}
.slider input[type=radio]:nth-child(2):checked~.bullets>label:nth-child(2){
    background-color: #fff;
}
.slider input[type=radio]:nth-child(3):checked~.bullets>label:nth-child(3){
    background-color: #fff;
}
.slider input[type=radio]:nth-child(4):checked~.bullets>label:nth-child(4){
    background-color: #fff;
}

가장 중요한 슬라이드 이동 애니메이션 효과를 만듭니다.

CSS 내용이 많지만 첫 번째 슬라이드를 배치한 방식만 이해하면 나머지는 가로 이동 위치와 배율 값만 조금씩 다르게 해서 입체적으로 보이도록 하는 것일 뿐 복잡한 것은 없습니다.

자바스크립트나 프리프로세서를 사용한다면 이런 반복되고, 다소 번거로운 작업을 아주 간편하게 구현할 수 있습니다.

첫 번째("/* 1 */") 슬라이드 배치를 보면 첫 번째 불릿이 선택되었을 경우에 슬라이드 4장의 위치를 정하고 있습니다.여기서는 CSS만으로 구현하는 것이므로 이런 방식으로 구현해야 한다고 이해를 해야 합니다.

첫 번째 슬라이드는 맨 앞에 그리고 순서대로 슬라이드들의 위치를 오른쪽으로 조금씩 밀고("left"), 크기를 조금씩 줄입니다.("transform: scale(0.8)")

이렇게 하면 입체적으로 층층이 배치된 슬라이드 모양이 만들어집니다.

레이어로 맨 위에 오는 슬라이드는 1을 지정하고 순서대로 뒤로 층이 내려갈 수록 0 -> -1 -> -2 로 부여해 순서대로 겹쳐지도록 합니다.

두 번째 불릿을 클릭하면 첫 번째 슬라이드는 왼쪽 한 층 밑으로 이동하고, 두 번째 슬라이드가 맨 앞 가운데 위치하게 됩니다. 마찬가지로 3번째와 4번째 슬라이드는 한 층씩 올라오는 배치를 가지게 됩니다.

레이어 순서도 두 번째 슬라이드가 1이 되고 첫 번째와 3번째는 0, 네 번째 슬라이드는 -1이 되도록 해서 순서를 맞추면 됩니다.

슬라이드 이동

첫 번째 슬라이드에서 만든 CSS 클래스를 복사해서 파라메터만 바꿔주면 되기 때문에 생각보다는 단순한 방식입니다.

같은 방식으로 세 번째, 네 번째 슬라이드 CSS를 만들면 애니메이션이 완성됩니다.

/* 1 */
.slider input[type=radio]:nth-child(1):checked~ul.imgs>li:nth-child(1){
    left: 0;
    transition: 0.75s;
    z-index:1;
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(1):checked~ul.imgs>li:nth-child(2){
    left: 90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(1):checked~ul.imgs>li:nth-child(3){
    left: 170px;
    transition: 0.75s;
    z-index:-1;
    transform: scale(0.8);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(1):checked~ul.imgs>li:nth-child(4){
    left: 230px;
    transition: 0.75s;
    z-index:-2;
    transform: scale(0.7);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}

/* 2 */
.slider input[type=radio]:nth-child(2):checked~ul.imgs>li:nth-child(1){
    left: -90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(2):checked~ul.imgs>li:nth-child(2){
    left: 0;
    transition: 0.75s;
    z-index:1;
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}

.slider input[type=radio]:nth-child(2):checked~ul.imgs>li:nth-child(3){
    left: 90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(2):checked~ul.imgs>li:nth-child(4){
    left: 170px;
    transition: 0.75s;
    z-index:-1;
    transform: scale(0.8);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}

/* 3 */
.slider input[type=radio]:nth-child(3):checked~ul.imgs>li:nth-child(1){
    left: -170px;
    transition: 0.75s;
    z-index:-1;
    transform: scale(0.8);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(3):checked~ul.imgs>li:nth-child(2){
    left: -90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(3):checked~ul.imgs>li:nth-child(3){
    left: 0;
    transition: 0.75s;
    z-index:1;
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(3):checked~ul.imgs>li:nth-child(4){
    left: 90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}


/* 4 */
.slider input[type=radio]:nth-child(4):checked~ul.imgs>li:nth-child(1){
    left: -230px;
    transition: 0.75s;
    z-index:-2;
    transform: scale(0.7);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(4):checked~ul.imgs>li:nth-child(2){
    left: -170px;
    transition: 0.75s;
    z-index:-1;
    transform: scale(0.8);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(4):checked~ul.imgs>li:nth-child(3){
    left: -90px;
    transition: 0.75s;
    z-index:0;
    transform: scale(0.9);
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}
.slider input[type=radio]:nth-child(4):checked~ul.imgs>li:nth-child(4){
    left: 0;
    transition: 0.75s;
    z-index:1;
    box-shadow: 14px -5px 35px -21px rgba(0,0,0,0.66);
}

완성된 슬라이드는 아래처럼 입체적으로 앞뒤로 이동하는 애니메이션을 보여주면서 슬라이드가 바뀌게 됩니다.

완성된 슬라이드