본문 바로가기
CSS

[css/scss] 그리드로 육각형 레이아웃 만들기

by F.E.D 2021. 1. 31.
<ul class="hex-grid__list">
    <li class="hex-grid__item">
        <div class="hex-grid__content">
            1
        </div>
    </li>
    <li class="hex-grid__item">
        <div class="hex-grid__content">
            2
        </div>
    </li>
    ...
</ul>

BEM(css 방법론 중 하나, Block-Element__Method)을 이용해서 작성했습니다.

.hex-grid__list {
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
}

위와 같이 만들어져야 하는 것입니다.

.hex-grid__list {
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
    grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr 1fr 2fr 1fr;
}

반복을 피하기 위해서 다시 한번 리팩토링 합니다.

.hex-grid__list {
    --amount: 5;
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
    grid-template-columns: repeat(var(--amount), 1fr, 2fr) 1fr;
}

우선 위와 같은 결과물이 나타나게 됩니다.

이제 이 그리드 항목들을 배치하면 됩니다.

.hex-grid__item {
    position: relative;
    grid-column: 1 / span 3;
    grid-row: 1 / span 2;
    height: 0;
    padding-bottom: 100%;
}

.hex-grid__content {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background-color: white;
}

 

scss를 사용해서 재배치 및 리팩토링 합니다.

$amount: 5;

.hex-grid__list {
    --amount: 5;
    --counter: 1;
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
    grid-template-columns: repeat(var(--amount), 1fr, 2fr) 1fr;
}

.hex-grid__item {
    position: relative;
    grid-column: 1 / span 3;
    grid-row: calc(var(--counter) + var(--counter)) / span 2;
    height: 0;
    padding-bottom: 100%;

    @for $i from 1 through 20 {
        &:nth-of-type(n + #{$i * $amount + 1}) {
            --counter: #{$i + 1};
        }
    }
}

.hex-grid__content {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background-color: white;
}

위의 반복구문을 css로 나타내면 다음과 같습니다.

.hex-grid__item:nth-of-type(n + 6) {
    --counter: 2;
}

.hex-grid__item:nth-of-type(n + 11) {
    --counter: 3;
}

.hex-grid__item:nth-of-type(n + 16) {
    --counter: 4;
}

/* ...etc */

거의 다 왔네요!

$amount: 5;

.hex-grid__list {
    --amount: 5;
    --counter: 1;
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
    grid-template-columns: repeat(var(--amount), 1fr, 2fr) 1fr;
}

.hex-grid__item {
    position: relative;
    grid-column: 1 / span 3;
    grid-row: calc(var(--counter) + var(--counter)) / span 2;
    height: 0;
    padding-bottom: 100%;

    // Columns
    @for $i from 1 through $amount {
        &:nth-of-type(#{$amount}n + #{$i}) {
            grid-column: #{$i + $i - 1} / span 3;
            @if $i % 2 == 0 {
                grid-row: calc(var(--counter) + var(--counter) - 1) / span 2;
            }
        }
    }

    // Rows
    @for $i from 1 through 20 {
        &:nth-of-type(n + #{$i * $amount + 1}) {
            --counter: #{$i + 1};
        }
    }
}

.hex-grid__content {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background-color: white;
}

위와 같이 배치 된 사각형들을 이제 clipping 하여 보여주도록 하겠습니다.

 

.hex-grid__item {
    /* snipped */
    height: 0;
    padding-bottom: 90%;
}

.hex-grid__content {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;
    background-color: white;
    clip-path: polygon(75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%, 25% 0);
    padding: 2rem 25%;
}

 

이제 gutter를 통해 여백만 조금 주면 될 듯 합니다. grid-gap을 사용해보세요!

.hex-grid__list {
    --amount: 5;
    --counter: 1;
    display: grid;
    list-style-type: none;
    margin: 0;
    padding: 0;
    grid-template-columns: repeat(var(--amount), 1fr, 2fr) 1fr;
    grid-gap: 1rem 2rem;
}

 

완성!!

반응형 코드까지 추가하면서 반복을 믹스인처리하면서 마무리 지어봅시다.

$block: '.hex-grid';

@mixin grid-item($amount) {
    @for $i from 1 through $amount {
        &:nth-of-type(#{$amount}n + #{$i}) {
            grid-column: #{$i + $i - 1} / span 3;
            @if $i % 2 == 0 {
                grid-row: calc(var(--counter) + var(--counter) - 1) / span 2;
            }
        }
    }

    @for $i from 1 through 20 {
        &:nth-of-type(n + #{$i * $amount + 1}) {
            --counter: #{$i + 1};
        }
    }
}

#{$block} {
    display: flex;
	justify-content: center;

    &__list {
        --amount: 5;
        position: relative;
        padding: 0;
		margin: 0;
		list-style-type: none;
		display: grid;
        grid-template-columns: repeat(var(--amount), 1fr 2fr) 1fr;
		grid-gap: 2.5rem 5rem;
    }

    &__item {
        position: relative;
		grid-column: 1 / span 3;
		grid-row: calc(var(--counter) + var(--counter)) / span 2;
		filter: drop-shadow(0 0 10px rgba(#444, .08));
		height: 0;
		padding-bottom: 90%;
    }

    &__content {
        position: absolute;
		height: 100%;
		width: 100%;
		font-size: 1.125rem;
		color: #111111;
		background-color: white;
		clip-path: polygon(75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%, 25% 0);
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		padding: 2rem 25%;
		text-decoration: none;
		text-align: center;
		transition: transform .24s ease-out;
    }
}

@media screen and (min-width: 1440px) {
	#{$block} {
		&__list {
            --amount: 5;
			--counter: 1;
		}

		&__item {
			@include grid-item(5);
		}
	}
}

@media screen and (min-width: 1120px) and (max-width: 1439px) {
	#{$block} {
		&__list {
            --amount: 4;
			--counter: 1;
		}

		&__item {
			@include grid-item(4);
		}
	}
}

@media screen and (min-width: 840px) and (max-width: 1119px) {
	#{$block} {
		&__list {
            --amount: 3;
			--counter: 1;
			grid-gap: 1.5rem 3rem;
		}

		&__item {
			@include grid-item(3);
		}
	}
}

@media screen and (min-width: 480px) and (max-width: 839px) {
	#{$block} {
		&__list {
			--amount: 2;
			--counter: 1;
			grid-gap: 1.5rem 3rem;
		}

		&__item {
			@include grid-item(2);
		}
	}
}

@media screen and (max-width: 479px) {
	#{$block} {
		&__list {
            --amount: 1;
			grid-gap: 1.5rem 3rem;
		}
	}
}

 

 

 

출처 : ninjarockstar.dev/css-hex-grids/

댓글