css선택자 문법의 일종으로 속성 선택자라는 것이 있다. 이 문법은 HTML요소의 특정 속성이나 값에 따라 요소를 선택하는데 사용된다.
기본 구문:
[attribute]: 해당 속성이 존재하는 모든 요소를 선택합니다.[attribute="value"]: 특정 속성이 지정한 값과 정확히 일치하는 요소를 선택합니다.[attribute*="value"]: 해당 속성 값에 지정한 문자열이 포함된 요소를 선택합니다.[attribute^="value"]: 해당 속성 값이 지정한 문자열로 시작하는 요소를 선택합니다.[attribute$="value"]: 해당 속성 값이 지정한 문자열로 끝나는 요소를 선택합니다.ex)
/* class 속성에 "button"이라는 문자열이 포함된 모든 요소 선택 */
[class*="button"] {}
/* class 속성이 "prefix-"로 시작하는 요소 선택 */
[class^="prefix-"] {}
/* class 속성이 "-active"로 끝나는 요소 선택 */
[class$="-active"] {}
/* class 속성이 "popup-"을 포함하고 "-active"로 끝나는 모든 section 요소 선택 */
section[class*="popup-"][class$="-active"] {}
이 속성을 이용해서 우리가 기존에 구현했던 팝업 코드에서 별도의 css속성을 추가하지 않더라도 요소를 추가함으로써 팝업이 늘어나도록 구조를 변경해보자.
원래 기존 css코드에서
.popup-1-actived,
.popup-1-actived > body {
overflow:hidden;
}
.popup-2-actived,
.popup-2-actived > body {
overflow:hidden;
}
이 코드를 수정해주어야 한다.
여기서 숫자를 제외한 popup-과 -actived는 중복되기에 이 코드를
[class*="popup-"][class*="-actived"],
[class*="popup-"][class*="-actived"] > body{
overflow:hidden;
}
이렇게 수정한다.
JS
function Popup__init(no) {
$('.btn-popup-' + no).click(function() {
Popup__show(no);
});
$('.popup-' + no + ' .popup__btn-close, .popup-' + no).click(function() {
Popup__hide(no);
});
$('.popup-' + no + ' .popup__content').click(function() {
return false;
});
}
function Popup__show(no) {
$('.popup-' + no).addClass('active');
$('html').addClass('popup-' + no + '-actived');
}
function Popup__hide(no) {
$('.popup-' + no).removeClass('active');
$('html').removeClass('popup-' + no + '-actived');
}
매개변수에 숫자가 들어가서 실행되면
$('html').~~~('popup-' + no + '-actived');
이 함수는 html태그에 popup-(매개변수)-actived를 추가하고 popup- 과 -actived클래스를 가지고 있는 태그들([class*="popup-"][class*="-actived"], [class*="popup-"][class*="-actived"] > body)에게 속성을 적용한다.
팝업 헤더의 높이를 css에 적지 않도록 flex를 이용해 다시 구현해보자.
.popup__content {
min-width:200px;
min-height:200px;
background-color:white;
border:2px solid black;
transform:translateY(-100%);
transition: transform .3s;
}
--->
.popup__content {
min-width:200px;
max-height:100%;
background-color:white;
border:2px solid black;
box-sizing:border-box;
transform:translateY(-100%);
transition: transform .3s;
display:flex;
flex-direction:column;
}
전체 팝업창의 높이를 지정하지 않았다가 100%로 지정해주고 display속성을 flex, 방향을 세로 방향으로 지정해준다. 또한 전체넓이에 border를 포함하도록 해준다.
.popup__body {
padding:0 10px;
max-height:calc(100vh - 55px);
overflow-y:auto;
}
--->
.popup__body {
padding:0 10px;
flex-grow:1;
overflow-y:auto;
}
원래 팝업의 body부분의 너비를 유연하게 만들기위해 max-height:calc(100vh - 55px);이 코드를 사용했지만 이제 팝업 header의 너비를 건들지 않고도 flex-glow를 이용해 유연하게 늘어나도록 만들었다.
그레이브 문법이란 백틱(x-shift~)을 이용한 방식으로 ${}를 사용해 문자열에 변수를 삽입할 수 있고
const a = 5;
const b = 10;
console.log(`The sum is ${a + b}`); // "The sum is 15"
이렇게 내부에 표현식을 넣어 계산된 결과를 문자열로 삽입할 수 있다.
위 내용을 바탕으로 우리가 구현했던 함수를 수정해보자.
function Popup__show(no) {
$('.popup-' + no).addClass('active');
$('html').addClass('popup-' + no + '-actived');
}
function Popup__hide(no) {
$('.popup-' + no).removeClass('active');
$('html').removeClass('popup-' + no + '-actived');
}
function Popup__init(no) {
$('.btn-popup-' + no).click(function() {
Popup__show(no);
});
$('.popup-' + no + ', .popup-' + no + ' .popup__btn-close').click(function() {
Popup__hide(no);
});
$('.popup-' + no + ' .popup__content').click(function() {
return false;
});
}
Popup__init(1);
Popup__init(2);
---->
function Popup__show(no) {
$(`.popup-${no}`).addClass('active');
$('html').addClass(`.popup-${no}-actived`);
}
function Popup__hide(no) {
$(`.popup-${no}`).removeClass('active');
$('html').removeClass(`.popup-${no}-actived`);
}
function Popup__init(no) {
$(`.btn-popup-${no}`).click(function() {
Popup__show(no);
});
$(`.popup-${no}, .popup-${no} .popup__btn-close`).click(function() {
Popup__hide(no);
});
$(`.popup-${no} .popup__content`).click(function() {
return false;
});
}
Popup__init(1);
Popup__init(2);
이번에는 처음부터 끝까지 테일윈드를 이용해 재구현해보자.
html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<div class="popup-1 popup fixed inset-0 flex items-center justify-center">
<!--
fixed -> position: fixed;
inset-0 -> top: 0px;, right: 0px;, bottom: 0px;, left: 0px;
flex -> display: flex;
items-center -> align-items: center;
justify-center -> justify-items: center;
-->
<div class="popup__content bg-white border-black border-2 max-h-full flex flex-col">
<!--
bg-white -> background-color: white;
border-black -> border-color: black;
border-2 -> border-width: 2px;
max-h-full -> max-height: 100%;
flex -> display: flex;
flex-col -> flex-direction: column;
-->
<div class="popup__head p-2">
<!--
p-2 -> padding: 0.5rem;
-->
<div class="popup__btn-close relative w-12 h-12 ml-auto cursor-pointer">
<!--
relative -> position: relative;
w-12 -> width: 3rem;
h-12 -> height: 3rem;
ml-auto -> margin-left: auto;
cursor-pointer -> cursor: pointer;
-->
</div>
</div>
<div class="popup__body p-2 flex-grow overflow-y-auto">
<!--
p-2 -> padding: 0.5rem;
flex-grow -> flex-grow: 1;
overflow-y-auto -> overflow-y: auto;
-->
<div class="container">
<!--
container -> 웹의 너비에 따라 너비를 조절
-->
Lorem ipsum...
</div>
</div>
</div>
</div>
<div class="popup-2 popup fixed inset-0 flex items-center justify-center">
<!--
fixed -> position: fixed;
inset-0 -> top: 0px;, right: 0px;, bottom: 0px;, left: 0px;
flex -> display: flex;
items-center -> align-items: center;
justify-center -> justify-items: center;
-->
<div class="popup__content bg-white border-black border-2 max-h-full flex flex-col">
<!--
bg-white -> background-color: white;
border-black -> border-color: black;
border-2 -> border-width: 2px;
max-h-full -> max-height: 100%;
flex -> display: flex;
flex-col -> flex-direction: column;
-->
<div class="popup__head p-2">
<!--
p-2 -> padding: 0.5rem;
-->
<div class="popup__btn-close relative w-12 h-12 ml-auto cursor-pointer">
<!--
relative -> position: relative;
w-12 -> width: 3rem;
h-12 -> height: 3rem;
ml-auto -> margin-left: auto;
cursor-pointer -> cursor: pointer;
-->
</div>
</div>
<div class="popup__body p-2 flex-grow overflow-y-auto">
<!--
p-2 -> padding: 0.5rem;
flex-grow -> flex-grow: 1;
overflow-y-auto -> overflow-y: auto;
-->
<div class="container">
<!--
container -> 웹의 너비에 따라 너비를 조절
-->
Lorem ipsum...
</div>
</div>
</div>
</div>
<section class="section-1">
<div class="container mx-auto">
<!--
container -> 웹의 너비에 따라 너비를 조절
mx-auto -> margin-left: auto;, margin-right: auto;
-->
<button class="btn-popup-1">팝업1</button>
<button class="btn-popup-2">팝업2</button>
</div>
<div class="container mx-auto">
<!--
container -> 웹의 너비에 따라 너비를 조절
mx-auto -> margin-left: auto;, margin-right: auto;
-->
Lorem ipsum...
</div>
</section>
css
.popup {
background-color:rgba(0,0,0,0.5);
visibility:hidden;
opacity:0;
transition:visibility 0.3s, opacity 0.3s;
}
.popup.active {
visibility:visible;
opacity:1;
}
.popup__content {
transform:translateY(-100%);
transition:transform 0.2s;
}
.popup.active .popup__content {
transform:translateY(0);
}
.popup__btn-close:hover {
transform:rotate(10deg);
}
.popup__btn-close::before,
.popup__btn-close::after {
content:"";
position:absolute;
top:40%;
left:0;
width:100%;
height:20%;
background-color:black;
transform:rotate(-45deg);
transition: box-shadow 0.2s;
}
.popup__btn-close::after {
transform:rotate(45deg);
}
.popup__btn-close:hover::before,
.popup__btn-close:hover::after {
box-shadow:0 0 10px rgba(0,0,0,0.5);
}
html[class*="popup-"][class*="-actived"],
html[class*="popup-"][class*="-actived"] > body {
overflow:hidden;
}
JS 부분은 동일