Front-End/HTML

HTML/CSS - a 태그를 이용하여 자동 스크롤 / 부드러운 스크롤

hyeeoooook 2025. 12. 12. 22:15

a태그를 이용하여 내가 원하는 위치로 이동하도록 하는 방식은 흔히 볼 수 있는 기술이다.

 

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>A태그를 이용하여 화면 이동하기</title>
    <link rel="stylesheet" href="./atag.css">
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="./jquery.scrollTo.js"></script>
</head>
<body>
    <div class="atag">
        <a class="header_a" href="#1">1로 이동</a>
        <a class="header_a" href="#2">2로 이동</a>
        <a class="header_a" href="#3">3로 이동</a>
        <a class="header_a" href="#4">4로 이동</a>
    </div>

    <h1 id="1">1</h1>
    <hr>
    <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, blanditiis perferendis totam, ducimus incidunt obcaecati in saepe tempore fugit veritatis ea voluptates illo vel, sint a! Voluptatum, sunt nisi! Eaque.
        Suscipit, in nesciunt voluptatem consequuntur dicta natus! Repudiandae accusamus blanditiis reiciendis nisi enim sequi voluptatibus quod necessitatibus fuga, culpa voluptatem eum neque adipisci suscipit debitis sint consectetur minus expedita placeat.
        Mollitia, eveniet illo dignissimos nulla fuga quisquam saepe quia sequi, animi nesciunt maiores modi soluta. Magnam, voluptate vel. Accusamus, ipsa. Eos dolores repellendus aut magni hic illo, aliquam id explicabo?
        Velit veritatis obcaecati enim exercitationem dignissimos? Temporibus assumenda fuga aperiam! Deleniti, excepturi aperiam voluptas impedit commodi veritatis quasi voluptate, magni quisquam quibusdam illo iste, quas reiciendis distinctio quod placeat sit?
        Porro sint beatae iusto voluptatem commodi numquam labore nostrum quo deserunt cum quos aut perferendis libero voluptas ratione maxime excepturi, inventore nemo distinctio sequi? Temporibus vero accusantium quidem sed voluptate!
        Sint molestias numquam adipisci amet non reiciendis soluta eos voluptates accusantium quasi a aut, alias voluptatum. Numquam laudantium pariatur odio quasi accusantium dolorem accusamus veniam, eum fuga aut voluptatum harum.
        Doloremque odit delectus alias libero fugiat cupiditate, consectetur, eveniet iure veritatis nihil asperiores eaque fuga, tenetur mollitia nobis praesentium sed ut et inventore! Sint obcaecati ipsam aspernatur, veritatis odio officia!
        Consectetur eum fugiat distinctio voluptatem earum harum sit quos cupiditate illum autem, nostrum nihil iusto eaque hic suscipit excepturi. Totam odit beatae magnam similique explicabo ratione dolorem dignissimos voluptas adipisci.
        Aut a repellendus nostrum, nesciunt rerum et quaerat architecto consequatur illo obcaecati! Esse sit ex voluptate, vitae eos libero est veniam itaque magnam asperiores beatae ad earum nisi nulla eveniet.
        Quod, sed consequatur laboriosam veritatis quo et magni dolorum impedit eius corporis delectus rem totam odit tempora reiciendis! Sit mollitia accusantium corrupti, unde cupiditate facilis minus id praesentium officiis repudiandae!
    </p>
    <a class="gototop" href="#">Go to top!</a>
    <h1 id="2">2</h1>
    <hr>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis repudiandae, consequatur, laudantium distinctio vero enim ex, facere sit quia maxime ipsum soluta? Mollitia, quibusdam sapiente laborum et sit temporibus explicabo?
        Nostrum aut esse voluptates totam sit necessitatibus minima dignissimos exercitationem accusamus placeat nihil ducimus non, maxime, amet quas maiores vero provident nesciunt consequuntur perspiciatis et quasi architecto, velit magnam? Soluta?
        Similique quo fugit inventore ipsum eius id laboriosam consectetur sunt nihil nesciunt, et tenetur voluptatem dolorem assumenda neque commodi sequi vero at cupiditate distinctio velit dolores nulla rem. Quaerat, asperiores?
        Recusandae accusantium explicabo quae totam consequatur, qui pariatur atque. Officiis enim in sed atque corporis laboriosam? Ea, delectus facilis ratione accusamus hic modi quaerat? Doloremque eos totam eum nemo dicta!
        Tempora unde sed culpa, ratione deleniti perspiciatis eaque repudiandae! Molestias mollitia culpa dolores assumenda quas ab aperiam vel tempora vitae minus? Velit voluptatem explicabo temporibus neque molestias dolores inventore repudiandae.
        Laboriosam sunt similique delectus, aliquam nam maxime eum, mollitia reprehenderit qui nulla, quo illo perspiciatis amet quibusdam! Dolorum voluptatem cupiditate soluta, enim suscipit dicta est dolorem iure animi itaque eaque!
        Esse quae, cum ea hic suscipit rerum nostrum? Ab eius expedita et possimus cumque optio omnis at cupiditate? Nihil eaque corporis, fuga enim consequuntur accusamus rem! Rerum officiis nesciunt aperiam!
        Saepe, totam, dolorum unde minus consequuntur repellendus repellat debitis aliquam eos laboriosam deserunt? Laudantium ipsum veniam ex aliquam repellat, non perspiciatis eos suscipit consequuntur. Distinctio autem quisquam quae odit vero.
        Itaque voluptatum sit laborum qui, eum provident. Tempore, eum natus magni obcaecati quasi delectus reiciendis nihil et iusto adipisci consequuntur possimus fugiat provident libero officiis vero doloremque consequatur debitis eligendi!
        Quisquam ullam odio natus hic aliquam ab laborum impedit vel, quia commodi adipisci cupiditate eos magnam veritatis libero repellendus? Mollitia soluta neque eveniet debitis eos iure optio sed rerum aliquam!
    </p>
    <a class="gototop" href="#">Go to top!</a>
    <h1 id="3">3</h1>
    <hr>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti eius nam eveniet voluptatum totam vel recusandae delectus modi? Eaque molestiae, corporis nisi dicta perferendis quis reiciendis. Fuga perspiciatis accusantium laudantium.
        Eos tenetur ullam consectetur, distinctio, recusandae beatae suscipit quisquam fuga veniam, quo aliquid facere ea nobis officiis harum? Facere enim iste vero fugit omnis, itaque quisquam excepturi animi quaerat incidunt.
        Enim perferendis possimus, consequatur aliquid in aperiam inventore eos? Totam, magnam! Adipisci delectus ipsam laborum consequuntur, tenetur, excepturi dolores officia ea, eius architecto expedita deserunt. Rem, ducimus? Incidunt, deleniti sapiente?
        Magnam molestias ut laborum, quisquam dolorum culpa magni esse, nulla dolore perferendis optio vero nisi sed officia eveniet delectus consectetur doloribus quod quia tenetur eum eius recusandae fuga. Deleniti, hic?
        Nesciunt laudantium, obcaecati odio eligendi quisquam nihil dolores ducimus expedita et doloremque dolorum totam debitis veritatis. Dolore, facilis quidem, assumenda, mollitia quisquam quam id ipsum et illum laudantium eos voluptate.
        Beatae a impedit magnam laudantium velit ducimus facere obcaecati, voluptatum sed consequatur tempora eum officia omnis consectetur veritatis odio ipsam iste, hic ex nisi architecto voluptates eius similique. Quia, culpa!
        Quos molestiae voluptatum perferendis in commodi ea quo, consequuntur odit? Aperiam ad deleniti, ut ipsum beatae debitis nisi officia quo accusantium perferendis explicabo dolorum? Dicta placeat laudantium reprehenderit assumenda provident?
        Aliquam animi adipisci recusandae doloribus possimus deleniti mollitia! Minus, nisi commodi, iure incidunt aut maiores dignissimos illo corrupti dolor nesciunt voluptatum adipisci aspernatur iusto! Quas sequi eum consectetur voluptates adipisci?
        Nulla, ut hic iste ducimus odit vel at, magnam aliquid unde temporibus non dicta molestias blanditiis, velit dolores eum rem voluptatibus eaque laboriosam consectetur similique atque officiis reiciendis ab! Architecto.
        Illum asperiores esse accusantium aut magnam, harum maxime ullam sunt, delectus laboriosam, vitae ab architecto? Ad totam cupiditate neque, quo maxime aliquid vitae tempora itaque cumque corporis animi officia perferendis.
    </p>
    <a class="gototop" href="#">Go to top!</a>
    <h1 id="4">4</h1>
    <hr>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla mollitia vitae ex? Mollitia ipsam quae, facilis odio dicta ipsum nam omnis earum perspiciatis aut dolore dignissimos veritatis quibusdam deleniti laborum.
        Optio ratione odit vero nam reprehenderit quibusdam odio suscipit quisquam et blanditiis quis nihil quasi, natus alias veritatis pariatur labore rerum! Assumenda maxime est enim perferendis quasi eligendi numquam dolorum.
        Minima deserunt repellendus perspiciatis veniam illum, nemo laudantium unde perferendis ad repellat omnis praesentium ab, at asperiores earum voluptas quisquam vitae nam ex impedit consequatur. Dolores, cupiditate? Earum, dignissimos. Eos.
        Aliquam iste libero exercitationem voluptatum a dolorem laudantium, sunt dicta soluta dolor! Deleniti magnam aspernatur eveniet! Ipsum deserunt, culpa id distinctio reiciendis explicabo praesentium vitae. Provident molestiae beatae deleniti quas.
        Labore excepturi vero facilis voluptas vitae porro veritatis, assumenda incidunt corporis enim dolor quibusdam voluptate. Quaerat deserunt earum quae quasi beatae at rem voluptates accusantium blanditiis nemo. Aspernatur, assumenda voluptates.
        Fugit totam aliquid error voluptates sint doloremque ut, in, aliquam explicabo suscipit aspernatur voluptatibus praesentium. Quasi tempore in perspiciatis at eius ratione quae commodi asperiores perferendis ullam dignissimos, harum aut?
        Minus quae perferendis dolores unde, architecto doloribus ea quisquam similique explicabo optio repellat ipsa sequi non iste dignissimos ullam. Ipsam delectus maiores quod voluptas accusantium consequatur culpa nulla molestiae eaque.
        Doloribus nemo voluptatum aut aliquid facere omnis accusantium nam aspernatur soluta nostrum. Perferendis id eum, iste magni atque eligendi quas possimus modi distinctio eaque labore aperiam provident delectus explicabo tenetur.
        Cum officiis repellendus veritatis, voluptatum modi ex voluptatem fugit magni eius neque earum sunt sed blanditiis voluptates, ad quisquam architecto officia sapiente dolorum, debitis vitae rerum natus. Atque, impedit temporibus?
        Ipsum aperiam sit aliquid nisi cupiditate ex odio pariatur ullam asperiores quidem officiis, delectus placeat vitae labore sunt voluptatum deleniti totam sapiente ducimus quod consectetur. Quas nulla ducimus aliquid nemo.
    </p>
    <a class="gototop" href="#">Go to top!</a>
    <!-- 그냥 #만 있을 경우 이 문서의 가장 최상단을 의미함-->
    
    <!-- J쿼리 방식 -->
     <!--
    <script>
        $('.header_a, .gototop').click(function(e){
            e.preventDefault();
            $.scrollTo(this.hash || 0, 900);
        })
    </script>
    -->
    <!-- J쿼리 방식 -->
</body>
</html>

 

CSS

/* Smooth Scroll */
html{
    scroll-behavior: smooth;
}

.atag a{
    background-color: teal;
    padding: 10px 20px;
    color: white;
    text-decoration: none;
}

 

JS

/*!
 * jQuery.scrollTo
 * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler
 * Licensed under MIT
 * https://github.com/flesler/jquery.scrollTo
 * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery
 * @author Ariel Flesler
 * @version 2.1.3
 */
;(function(factory) {
	'use strict';
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['jquery'], factory);
	} else if (typeof module !== 'undefined' && module.exports) {
		// CommonJS
		module.exports = factory(require('jquery'));
	} else {
		// Global
		factory(jQuery);
	}
})(function($) {
	'use strict';

	var $scrollTo = $.scrollTo = function(target, duration, settings) {
		return $(window).scrollTo(target, duration, settings);
	};

	$scrollTo.defaults = {
		axis:'xy',
		duration: 0,
		limit:true
	};

	function isWin(elem) {
		return !elem.nodeName ||
			$.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;
	}

	function isFunction(obj) {
		// Brought from jQuery since it's deprecated
		return typeof obj === 'function'
	}

	$.fn.scrollTo = function(target, duration, settings) {
		if (typeof duration === 'object') {
			settings = duration;
			duration = 0;
		}
		if (typeof settings === 'function') {
			settings = { onAfter:settings };
		}
		if (target === 'max') {
			target = 9e9;
		}

		settings = $.extend({}, $scrollTo.defaults, settings);
		// Speed is still recognized for backwards compatibility
		duration = duration || settings.duration;
		// Make sure the settings are given right
		var queue = settings.queue && settings.axis.length > 1;
		if (queue) {
			// Let's keep the overall duration
			duration /= 2;
		}
		settings.offset = both(settings.offset);
		settings.over = both(settings.over);

		return this.each(function() {
			// Null target yields nothing, just like jQuery does
			if (target === null) return;

			var win = isWin(this),
				elem = win ? this.contentWindow || window : this,
				$elem = $(elem),
				targ = target,
				attr = {},
				toff;

			switch (typeof targ) {
				// A number will pass the regex
				case 'number':
				case 'string':
					if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
						targ = both(targ);
						// We are done
						break;
					}
					// Relative/Absolute selector
					targ = win ? $(targ) : $(targ, elem);
					/* falls through */
				case 'object':
					if (targ.length === 0) return;
					// DOMElement / jQuery
					if (targ.is || targ.style) {
						// Get the real position of the target
						toff = (targ = $(targ)).offset();
					}
			}

			var offset = isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;

			$.each(settings.axis.split(''), function(i, axis) {
				var Pos	= axis === 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					prev = $elem[key](),
					max = $scrollTo.max(elem, axis);

				if (toff) {// jQuery / DOMElement
					attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);

					// If it's a dom element, reduce the margin
					if (settings.margin) {
						attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;
						attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;
					}

					attr[key] += offset[pos] || 0;

					if (settings.over[pos]) {
						// Scroll to a fraction of its width/height
						attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];
					}
				} else {
					var val = targ[pos];
					// Handle percentage values
					attr[key] = val.slice && val.slice(-1) === '%' ?
						parseFloat(val) / 100 * max
						: val;
				}

				// Number or 'number'
				if (settings.limit && /^\d+$/.test(attr[key])) {
					// Check the limits
					attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);
				}

				// Don't waste time animating, if there's no need.
				if (!i && settings.axis.length > 1) {
					if (prev === attr[key]) {
						// No animation needed
						attr = {};
					} else if (queue) {
						// Intermediate animation
						animate(settings.onAfterFirst);
						// Don't animate this axis again in the next iteration.
						attr = {};
					}
				}
			});

			animate(settings.onAfter);

			function animate(callback) {
				var opts = $.extend({}, settings, {
					// The queue setting conflicts with animate()
					// Force it to always be true
					queue: true,
					duration: duration,
					complete: callback && function() {
						callback.call(elem, targ, settings);
					}
				});
				$elem.animate(attr, opts);
			}
		});
	};

	// Max scrolling position, works on quirks mode
	// It only fails (not too badly) on IE, quirks mode.
	$scrollTo.max = function(elem, axis) {
		var Dim = axis === 'x' ? 'Width' : 'Height',
			scroll = 'scroll'+Dim;

		if (!isWin(elem))
			return elem[scroll] - $(elem)[Dim.toLowerCase()]();

		var size = 'client' + Dim,
			doc = elem.ownerDocument || elem.document,
			html = doc.documentElement,
			body = doc.body;

		return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);
	};

	function both(val) {
		return isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };
	}

	// Add special hooks so that window scroll properties can be animated
	$.Tween.propHooks.scrollLeft =
	$.Tween.propHooks.scrollTop = {
		get: function(t) {
			return $(t.elem)[t.prop]();
		},
		set: function(t) {
			var curr = this.get(t);
			// If interrupt is true and user scrolled, stop animating
			if (t.options.interrupt && t._last && t._last !== curr) {
				return $(t.elem).stop();
			}
			var next = Math.round(t.now);
			// Don't waste CPU
			// Browsers don't render floating point scroll
			if (curr !== next) {
				$(t.elem)[t.prop](next);
				t._last = this.get(t);
			}
		}
	};

	// AMD requirement
	return $scrollTo;
});

JS는 CDN 방식으로도 가능하다.

<script src="https://cdn.jsdelivr.net/npm/jquery.scrollto@2.1.3/jquery.scrollTo.min.js"></script>
<!-- 또는 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-scrollTo/2.1.3/jquery.scrollTo.min.js"></script>

 


궁금했던 내용

JS와 CSS가 싸우면 누가 이길까?

그래서 문득 js와 css를 모두 주석처리 하지 않고 실행을 시켜보았다.

결과는 스크롤이 그냥 튀었다. 때론 목적지를 향해 가기도 하였다.

 

JS코드의 시간을 10초로 지정하여 실행해 본 결과는 결국 마지막까지 천천히 목적지로 이동하였다.

 

결과는 다음과 같았다.

CSS를 먼저 호출 -> JS코드가 실행되는 구조였다.

 

 

CSS의 scroll-behavior은 JS코드에서의 몇 초 정도일까?

일단 대략적으로 비교해본 결과 각 브라우저마다 달랐다. 크롬과 엣지의 경우에 0.3초 정도였다. 파이어폭스의 경우 0.4 ~ 0.5초 정도였다.

 

브라우저마다 다른 scroll-behavior 속성의 차이점

크롬과 엣지의 경우 서서히 움직여서 위치에서 자석처럼 탁 붙는 느낌이었고

파이어 폭스의 경우는 쫀득하게 붙는 느낌으로 서로 달랐다.

 

 

JS쿼리 방식 vs CSS 방식

정확하게 말하자면 CSS방식보단 브라우저마다 다르게 구현된 scroll-behavior 속성차이겠지만, 둘의 차이점은 명확하다.

 

JS쿼리 방식
내가 직접 시간 조절가능
추가적인 코드작성이 없는 경우 거리와 상관없이 무조건 정해진 시간에 도착(CSS방식보단 약간 투박함 / 단, 추가적 커스텀 가능)
하지만, 이를 (targetTop - currentTop) * (숫자) = speed를 통해서 거리 비례 스피드를 조절할 수 있다.
CSS방식
브라우저마다 정해놓은 시간개념이 존재
거리가 가까울수록 빨리도착, 멀수록 늦게 도착
단순하게 부드러운 스크롤을 원한다면 사용하기 편함

 

'Front-End > HTML' 카테고리의 다른 글

HTML - 트위터 클론 코딩 - 2  (0) 2025.12.15
HTML - 트위터 클론 코딩 - 1  (1) 2025.12.13
HTML/CSS - 비디오 메인화면 제작하기  (2) 2025.12.12
HTML/CSS - <header>  (0) 2025.11.25
[CSS] Scroll-Snap  (0) 2025.11.23