본문 바로가기

티스토리 현재 페이지에서 찾는 본문 검색창 (Ctrl + F)

by JINYH 2022. 1. 17.
728x90
반응형

아래 이미지와 같이 누구나 한 번쯤은 '현재 페이지'에서 원하는 내용을 찾기 위해 '컨트롤(Ctrl) + F'로 단어 검색을 해 본 적이 있을 것이다.

 

01-컨트롤-f

 

 

 

먼저 이 '컨트롤(Ctrl) +F 단어 검색 기능'을 요약정리해 보겠다. (이 부분을 잘 알아야 뒤에서 나오는 HTML 및 CSS를 더 잘 이해할 수 있다.)

 

① '현재 페이지'에서 '검색 단어'와 일치하는 단어 (이하 '일치 단어') 찾기

② '일치 단어'의 전체 개수를 숫자로 표기 (ex : 36)

③ '일치 단어'를 노란색으로 마크(mark) 처리

④ 상단에서 하단 방향으로 '일치 단어'에 자동으로 번호 지정

⑤ '일치 단어' 중 '현재 단어'의 번호를 숫자로 표기 (ex : 10)

⑥ '일치 단어' 중 '현재 단어'를 주황색으로 마크(mark) 처리

⑦ '∧' 버튼 클릭 시 '이전 단어' 찾기

- 화면 이동, 마크(mark) 색상 변경, 번호 변경 (-1)

⑧ '∨' 버튼 클릭 시 '다음 단어' 찾기

- 화면 이동, 마크(mark) 색상 변경, (+1)

⑨ 'Ⅹ' 버튼 클릭 시 검색 결과 초기화 및 검색창 제거

 

 

 

상기 요약 내용과 같이 웹사이트 방문자가 원하는 내용을 쉽고 빠르게 찾을 수 있도록 도와주는 '현재 페이지 내 단어 검색 기능'은 웹사이트 이용 환경 구축에 필수 요소라고 할 수 있다.

 

이미 PC에는 '컨트롤(Ctrl) + F 단어 검색 기능'이 있고 Mobile에는 '페이지 내 검색 기능'이 있다. 그런데 이 기능을 알고 있는 방문자의 경우 웹사이트를 잘 이용할 수 있지만, 이 기능의 존재 유무조차 모르는 방문자의 경우 웹사이트에 오래 머물지 못하고 쉽게 이탈할 수도 있다.

 

 

 

'수익형 티스토리 블로그'를 생각해 볼 때 방문자의 만족도는 물론, 체류 시간 증대와 이탈률 감소를 위해 화면 상단에 고정된 플로팅 검색창을 적용하는 것이 좋겠다.

 

본 글은 북클럽 스킨을 기준으로 현재 페이지에서 찾아 주는 플로팅 검색창을 생성하는 방법에 대한 내용이며, 상세히 설명했으니 각자의 티스토리에 적용해 보기 바란다.

 

 

 

 

 


 

 

 

 

 

미리 보기

 

먼저 작업 결과이다.

 

상기 설명한 '컨트롤(ctrl) + F 단어 검색 기능'과 거의 동일하게 구현했고, Mobile에서도 이상 없이 작동하는 것을 확인할 수 있다.

 

PC든 Mobile이든 글이 길면 이탈률이 높아질 것 같아서 걱정이 되면서도 체념할 수밖에 없었는데, 플로팅 검색창을 달고 나니 마음이 한결 가벼워졌다.

 

02-미리보기-pc
03-미리보기-mobile

 

 

 

 

 

1] 검색창 생성

 

가장 먼저 검색창을 생성한다.

 

검색창은 웹사이트 방문자가 '현재 페이지'의 첫 화면에서 스크롤을 내리기 전에 쉽게 발견할 수 있어야 하기 때문에, 기본적으로 검색창의 위치는 '현재 페이지'의 최상단이 가장 좋다.

 

검색창을 본문 최상단에 생성하기 위해 아래 코드를 HTML의 <div class="entry-content"> 위에 삽입한다.

 

<div class="search-in-body">
	<input type="search" class="search-box" placeholder="본문 검색">
	<button data-search="next" class="next-btn">∨</button>
	<button data-search="prev" class="prev-btn">∧</button>
	<button data-search="clear" class="clear-btn">Ⅹ</button>
	<span class="kwt-count">-</span>
	</div>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

[ 2 ]

input typesearch로 해야 '단어 입력란'이 생성된다.

placeholder는 '단어 입력란'에 단어를 입력하기 전, '단어 입력란'에 고정적으로 출력되어 있는 문구에 해당하며, 나는 웹사이트 방문자의 이해를 돕고 검색을 유도하기 위해 '본문 검색'을 삽입했다.

 

[ 3 ~ 5 ]

button data-search로 '다음 단어', '이전 단어', '단어 입력란 초기화' 버튼을 생성한다. 버튼 안에 들어가는 내용은 <button ~ > ~ </button> 사이에 삽입하면 되는데, 나는 검색창의 면적을 최소화하기 위해 기호('∧', '∨', 'ⅹ')를 삽입했다.

 

[ 6 ]

kwt-count는 '숫자('현재 단어'의 번호) / 숫자('일치 단어'의 전체 개수)'에 해당한다. <span ~ > ~ </span> 사이에는 단어를 검색하기 전에 출력할 문구를 삽입하면 되는데, 나는 '하이픈(-)'을 삽입했다. ('0 / 0' 도 가능)

 

[ 1 ]

마지막으로 CSS 스타일 적용을 위해 '검색창 전체'를 div 코드로 감싸 주었다. search-in-body 포함 모든 'class'의 값들은 수정 가능하다.

 

 

 

상기 코드를 삽입하면 검색창이 아래와 같이 생성된다.

 

05-검색창-생성-결과

 

 

 

아래 코드를 CSS에 삽입해서 레이아웃 등 검색창의 기본적인 스타일을 적용한다.

 

.search-in-body {
	display: flex;
	flex-direction: row;
	background-color: #eee;
	z-index: 999;
}
.search-box {
	width: 40%;
	border: 1px solid #eee;
	padding: 3px 3px 3px 3px;
	margin: 5px 3px 5px 5px;
}
.next-btn,
.prev-btn,
.clear-btn {
	width: 10%;
	padding: 0px 3px 0px 3px;
	margin: 5px 3px 5px 3px;
	border: 2px solid white;
}
.kwt-count {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 30%;
	padding: 0px 3px 0px 3px;
	margin: 5px 5px 5px 3px;
	border: 2px solid white;
}

 

 

 

[ 1 ~ 6 / search-in-body ]

'검색창 전체'에 해당하는 코드다.

display: flex;, flex-direction: row;로 가로 정렬을 하고, 검색창과 본문의 영역을 구분 지을 수 있도록 background-color로 검색창의 배경 색상을 지정하고, 검색창이 다른 개체에 가려지지 않도록 z-index로 검색창의 Z축을 지정한다.

 

[ 8, 16, 25 / width ]

width는 가로길이에 해당하며, 출력될 위치에 따라 자동으로 가로길이가 정해지도록 가로길이를 'px' 단위가 아닌 '%' 단위로 지정했다. 해서 search-box는 '40%;', btn은 각각 '10%;', kwt-count는 '30%;'의 비율을 지정하여 '100%'를 맞췄다. 내가 search-in-bodywidth를 별도로 지정하지 않았기 때문에, 본문 영역의 가로길이에 따라 자동으로 가로길이가 정해진다.

 

[ border, padding, margin ]

각각의 영역을 구분해주고, 간격을 맞추기 위해 적정 값을 지정한다.

 

[ 22 ~ 24 ]

kwt-count는 버튼 안에 들어가는 것이 아니기 때문에 기본적으로 중앙 정렬이 되어 있지 않다. display: flex;, justify-content: center;, align-items: center;로 중앙 정렬 한다.

 

 

 

상기 코드를 삽입하면 검색창이 아래와 같이 기본적인 외형을 갖춘다.

 

06-검색창-생성-css-결과

 

 

 

 

 

2] var, 변수 선언

 

아래 var 코드 [ 3 ~ 20 ] 를 HTML에 추가 삽입해서 변수를 선언한다.

 

	</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"></script>

<script>
	document.body.onload = function() {
		var $input = document.querySelector("input[type='search']"),
				$clearBtn = document.querySelector("button[data-search='clear']"),
				$prevBtn = document.querySelector("button[data-search='prev']"),
				$nextBtn = document.querySelector("button[data-search='next']"),
				$content = document.querySelector(".entry-content"),
				$contentMark = new Mark($content),
				$results,
				currentClass = "current",
				offsetTop = 200,
				currentIndex = 0;
		var variableCounter = 0;
		var totalCount = 0;
	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

[ 3 / mark.min.js ]

mark 자바스크립트 코드를 삽입해야 검색 시 '일치 단어'에 노란색 마크(mark) 처리가 정상적으로 작동한다.

 

[ 11 / content ]

북클럽 스킨을 기준으로 본문에 해당하는 entry-content를 삽입한다.

 

[ 15 / offsetTop ]

'현재 단어'가 화면 상 위치하는 높이에 해당하며, 검색에 따른 화면 이동 시 이 값을 기준으로 이동한다.

 

[ 16 / currentIndex ]

현재 활성화된 인덱스에 해당하며, '0'으로 지정한다.

 

[ 17 / variableCounter ]

'현재 단어'의 번호에 해당하며, '0'으로 지정한다.

 

[ 18 / totalCount ]

'일치 단어'의 전체 개수에 해당하며, '0'으로 지정한다.

 

 

 

 

 

3] input, 기능 설정

 

아래 input 코드 [ 4 ~ 12 ] 를 HTML에 추가 삽입해서 'input' 기능을 설정한다.

 

'단어 입력란'에 단어('value')를 입력하면 '일치 단어'를 마크(mark) 처리한다는 내용이다.

 

<script>
		var totalCount = 0;

		$input.addEventListener("input", function() {
			var searchVal = this.value;
			$contentMark.unmark( {
				done: function(totalMatches) {
					$contentMark.mark(searchVal, {
					});
				}
			});
		});

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

아래 kwt-count 코드 [ 4 ~ 13 ] 를 HTML에 추가 삽입해서 '일치 단어'의 전체 개수에 대한 'count' 기능을 설정한다.

 

'일치 단어'의 전체 개수를 totalCount로 설정하고 '현재 단어'의 번호를 '1'로 지정해서, kwt-count를 '숫자('현재 단어'의 번호) / 숫자('일치 단어'의 전체 개수)'로 표기한다는 내용이다.

 

<script>
					$contentMark.mark(searchVal, {

						separateWordSearch: false,
						acrossElements: true,
						done: function(totalMatches) {
							$results = $content.querySelectorAll("mark");
							totalCount = totalMatches;
							if (totalCount) {
								variableCounter = 1;
								$(".kwt-count").html(variableCounter+ " / " +totalCount);
							}
						}

					});
				}
			});
		});

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

아래 mark 코드를 CSS에 추가 삽입해서 '일치 단어'의 마크(mark) 처리를 노란색으로, '현재 단어'의 마크(mark) 처리를 주황색으로 설정한다.

 

mark {
	background: yellow;
}
mark.current {
	background: orange;
}

 

 

 

여기까지 완료하면 검색창이 아래와 같이 나타난다.

 

08-jump-기능

 

 

 

 

 

4] prev & nextBtn, 찾기 기능 설정

 

아래 prevBtn, nextBtn 코드 [ 10 ~ 24 ] 를 HTML에 추가 삽입해서 '이전 및 다음 버튼'의 찾기 기능을 설정한다.

 

<script>
								$(".kwt-count").html(variableCounter+ " / " +totalCount);
							}
						}
					});
				}
			});
		});

		$nextBtn.addEventListener("click", prevNextHandler);
		$prevBtn.addEventListener("click", prevNextHandler);
		$nextBtn.after($prevBtn);
		function prevNextHandler() {
			if ($results.length) {
				currentIndex += (this.dataset.search === "prev" ? -1 : 1);
				if (currentIndex < 0) {
					currentIndex = $results.length - 1;
				}
				if (currentIndex > $results.length - 1) {
					currentIndex = 0;
				}
				jumpTo();
			}
		}

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

[ 10, 11 ]

버튼 클릭에 대한 이벤트 코드로, 이 코드를 삽입해야 버튼 클릭 기능이 정상적으로 작동한다.

 

[ 15 ]

'-1'과 '1'로 삽입해야 버튼을 클릭했을 때 '현재 단어'에서 '이전 및 다음 단어'를 한 단계씩 찾는다. 예를 들어 '-2'와 '2'로 삽입할 경우 '10번 단어'에서 '다음 버튼'을 클릭 시 '12번 단어'를 찾게 되고, '10번 단어'에서 '이전 버튼'을 클릭 시 '8번 단어'를 찾게 된다.

 

[ 16 ~ 21 ]

이 코드를 삽입해야 '1번 단어'에서 '이전 버튼'을 클릭 시 '마지막 단어'를 찾을 수 있고, '마지막 단어'에서 '다음 버튼'을 클릭 시 '1번 단어'를 찾을 수 있다.

 

 

 

 

 

5] prev & nextBtn, Count 기능 설정

 

아래 count 코드 [ 6 ~ 20 ] 를 HTML 추가 삽입해서 '현재 단어'의 번호에 대한 'count' 기능을 설정한다.

 

'이전 버튼'을 클릭 시 '현재 단어'의 번호에서 '-1' 처리되고, '다음 버튼'을 클릭 시 '현재 단어'의 번호에서 '+1' 처리된다는 내용이다.

 

<script>
				jumpTo();
			}
		}

		$("[data-search=next]").click(function() {
			if (variableCounter < totalCount)
				variableCounter = variableCounter + 1;
			else
				variableCounter = 1;
			$(".kwt-count").html(variableCounter+ " / " +totalCount);
		})

		$("[data-search=prev]").click(function() {
			if (variableCounter > 1)
				variableCounter = variableCounter - 1;
			else
				variableCounter = totalCount;
			$(".kwt-count").html(variableCounter+ " / " +totalCount);
		})

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

 

 

6] jumpTo, 화면 이동 기능 설정

 

아래 jumpTo 코드 [ 5 ~ 16 ] 를 HTML에 추가 삽입해서 버튼 클릭 시 화면 이동 기능을 설정한다.

 

앞서 '현재 단어'의 offsetTop을 설정했는데, 버튼 클릭 시 설정한 offsetTop 위치에 맞게 화면을 이동시킨다는 내용이다.

 

<script>
			$(".kwt-count").html(variableCounter+ " / " +totalCount);
		})

		function jumpTo() {
			if ($results.length) {
				var position,
						$current = $results[currentIndex];
				$results.forEach($result => $result.classList.remove(currentClass));
				if ($current) {
					$current.classList.add(currentClass);
					position = $current.offsetTop - offsetTop;
					window.scrollTo(0, position);
				}
			}
		}

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

 

 

7] clearBtn, 초기화 기능 설정

 

아래 clearBtn 코드 [ 7 ~ 14 ] 를 HTML에 추가 삽입해서 '클리어 버튼'의 초기화 기능을 설정한다.

 

버튼 클릭 시 '일치 단어'가 언마크(unmark) 처리되고, '단어 입력란'에 입력된 단어가 삭제되고, kwt-count의 문구가 '하이픈(-)'으로 변경된다는 내용이다.

 

<script>
					window.scrollTo(0, position);
				}
			}
		}

		$clearBtn.addEventListener("click", function() {
			$contentMark.unmark();
			$input.value = ""
			$input.focus();
			variableCounter = 0;
			totalCount = 0;
			$(".kwt-count").html("-");
		});

	};
	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

 

 

8] 화면 우측 고정 설정

 

아래 코드를 CSS에 추가 삽입해서 검색창을 화면 우측에 고정한다.

 

position: fixed;로 검색창의 위치를 고정시키고, 고정시킬 위치는 right: 20px;로 지정한다. 또한 우측 공간의 면적을 고려해서 검색창의 가로길이를 width: 300px;로 지정한다.

 

.search-in-body {
	position: fixed;
	right: 20px;
	width: 300px;
	box-shadow: 0px 0px 5px rgba(0,0,0,0.5);
}

 

 

 

상기 코드를 삽입하면 검색창이 아래와 같이 화면 우측에 고정된다.

 

09-검색창-우측-고정

 

 

 

 

 

9] 화면 우측 상단 플로팅 설정

 

아래 scroll 코드 [ 7 ~ 21 ]를 HTML에 추가 삽입해서 검색창을 화면 우측 상단에 플로팅으로 고정한다.

 

스크롤을 일정 부분까지 내리면 CSS 스타일 중 sib-fixed가 적용되고 sib-absolute는 해제된다는 내용이고, 스크롤을 일정 부분까지 올리면 반대로 sib-absolute가 적용되고 sib-fixed는 해제된다는 내용이다.

 

<script>
			$(".kwt-count").html("-");
		});

	};

	$(document).ready(function () {
		$(".search-in-body").addClass("sib-absolute");

		var sib = $(".search-in-body").offset().top - 165;
		$(window).scroll(function () {
			if ($(this).scrollTop() >= sib) {
				$(".search-in-body").addClass("sib-fixed");
        $(".search-in-body").removeClass("sib-absolute");
			}
			else {
				$(".search-in-body").addClass("sib-absolute");
        $(".search-in-body").removeClass("sib-fixed");
			}
		});
	});

	</script>


							<div class="entry-content">
								##_article_rep_desc_##

 

 

 

아래 코드를 CSS에 추가 삽입하고 search-in-bodyposition: fixed;는 삭제한다.

 

.sib-absolute {
	position: absolute;
}
.sib-fixed {
	position: fixed;
	top: 80px;
}

 

 

 

여기까지 완료하면 검색창이 아래와 같이 생성된다.

 

10-우측-상단-고정

 

 

 

 

 

10] Mobile에서의 스타일 적용

 

아래 코드를 CSS에 추가 삽입해서 Mobile 화면에서의 스타일을 적용한다. (세부 내용 생략)

 

@media screen and (max-width: 800px) {
	.search-in-body {
		display: flex;
		flex-direction: row;
		position: fixed;
		right: 20px;
		left: 20px;
		width: auto;
		top: 75px;
	}
	.search-box {
		width: 40%;
		margin-left: 5px;
		padding-left: 10px;
	}
	.next-btn,
	.prev-btn {
		width: 10%;
		padding-right: 3px;
		padding-left: 3px;
		margin-right: 3px;
		margin-left: 3px;
		color: black;
	}
	.clear-btn {
		width: 10%;
		padding-right: 3px;
		padding-left: 3px;
		margin-right: 3px;
		margin-left: 3px;
		color: black;
	}
	.kwt-count {
		width: 30%;
		display: flex;
		justify-content: center;
		align-items: center;
		padding-right: 3px;
		padding-left: 3px;
		margin-right: 5px;
		margin-left: 3px;
		color: black;
	}
}

 

 

 

 

 

11] HTML 전체 코드

11-html-전체

 

 

 

 

 

12] CSS 전체 코드

12-css-전체

 

 

 

 

 

728x90
반응형