当我们给元素加上 overflow: auto;  的时候,就会出现滚动条,然而浏览的不同,滚动条的样式大不一样,有些甚至非常丑。

于是就想着自己写一个滚动条,大概需要弄清楚一下这几个点:

1、滚动条 bar 是根据内容的多少,高度不一样的,这个需要动态的计算

2、滚动条 bar 的 top 位置 和 内容scrollTop 的关系。

思路:

使用嵌套的布局,如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.wrap{
width: 400px;
height: 400px;
border: 2px solid deeppink;
margin: 0 auto;
overflow: hidden;
position: relative;
}
.box-middle{
height: 100%;
overflow: auto;
width: 200%;
}
.box{
width: 50%;
}
.bar{
background: #000;
width: 10px;
position: absolute;
top: 0;
right: 0;
}
.s1{
height: 400px;
background: pink;
}
.s2{
height: 400px;
background: deeppink;
}
.s3{
height: 400px;
background: deepskyblue;
}
</style>
</head>
<body>
<div class="wrap" id="wrap">
<div class="box-middle" id="boxMidle">
<div class="box" id="content">
<div class="s1">内容1</div>
<div class="s2">内容2</div>
<div class="s3">内容3</div>
</div>
</div>
<div class="bar" id="bar"></div>
</div> </body> </html>

  

wrap 为最外层,给overflow:hidden;。

box-middle 是中间层,也是有滚动条的一层,可以宽度给多一点,这样就看不见滚动条了。

box就是内容层,通过js,计算使得 box 的宽度和wrap 保持一致,这样就完全看不见滚动条了

bar 为滚动条

写js之前,首先要弄懂一下三个属性:

offsetHeight : height + padding + border

clientHeight :  height + padding

scrollHeight : 内容的高度(所有子元素高度和) + padding

  

1、计算比例:

  bar的高度 / wrap的高度 =  wrap的高度 / wrap 内容部子元素的高度和      ;  此时忽略 wrap 的padding:0

bar的top  /  wrap的scrollTop      =   wrap的高度 / wrap 内容部子元素的高度和   ;

需要注意,当比例 的 值 小于 1 的时候,说明 这个时候没有出现滚动条。

知道算法之后,写代码就简单很多,普通版代码如下:

	 	var $wrap = document.getElementById("wrap");
var $boxMidle = document.getElementById("boxMidle");
var $content = document.getElementById("content");
var $bar = document.getElementById("bar");
$content.style.width = $wrap.clientWidth + "px"; //内容的宽度
var rate = $boxMidle.clientHeight/ $boxMidle.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
var barHeight = rate * $boxMidle.clientHeight; //滚动条的 bar 的高度
if(rate < 1){
//需要出现滚动条,并计算滚动条的高度
$bar.style.height = barHeight + "px";
}else{
//不需要出现滚动条
$bar.style.display = "none";
} $boxMidle.onscroll = function(e){
console.log("offsetHeight"+this.offsetHeight); //height + padding + border
console.log("clientHeight"+this.clientHeight); // height + padding
console.log("scrollHeight"+this.scrollHeight); //内容的高度(所有子元素高度和) + padding
console.log(this.scrollTop);
$bar.style.top = this.scrollTop*rate + "px";
}

  

使用面向对象版:

		function ScrollBar(opt){
var me = this;
me.$wrap = document.getElementById(opt.wrap);
me.$boxMidle = document.getElementById(opt.boxMidle);
me.$content = document.getElementById(opt.content);
me.$bar = document.getElementById(opt.bar);
me.init();
me.$boxMidle.onscroll = function(e){
//console.log("offsetHeight"+this.offsetHeight); //content + padding + border
//console.log("clientHeight"+this.clientHeight); // content + padding
//console.log("scrollHeight"+this.scrollHeight); //内容的高度 + padding
console.log(this.scrollTop);
me.scrollToY(this.scrollTop * me.rate)
}
}
ScrollBar.prototype.init = function(){
this.$content.style.width = this.$wrap.clientWidth + "px"; //内容的宽度
this.rate = this.$boxMidle.clientHeight/this.$boxMidle.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
this.barHeight = this.rate * this.$boxMidle.clientHeight; //滚动条的 bar 的高度
if(this.rate < 1){
//需要出现滚动条,并计算滚动条的高度
this.$bar.style.height = this.barHeight + "px";
}else{
//不需要出现滚动条
this.$bar.style.display = "none";
}
}
ScrollBar.prototype.scrollToY = function(y){
if(this.rate < 1){
this.$bar.style.top = y + 'px';
}
} var obj = new ScrollBar({"wrap":"wrap","boxMidle":"boxMidle","content":"content","bar":"bar"});

  

最后看一下效果:

虽然效果很丑,但是可控,自己调一下就可以了

使用 js,自己写一个简单的滚动条的更多相关文章

  1. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  2. 用node.js从零开始去写一个简单的爬虫

    如果你不会Python语言,正好又是一个node.js小白,看完这篇文章之后,一定会觉得受益匪浅,感受到自己又新get到了一门技能,如何用node.js从零开始去写一个简单的爬虫,十分钟时间就能搞定, ...

  3. 用JavaScript写一个简单的计算器

    本文使用js实现了一个简单的加.减.乘.除计算器. 以下是css部分代码: *{ padding:0; margin:0; color: #424242; } .outer{ width:300px; ...

  4. express 写一个简单的web app

    之前写过一个简单的web app, 能够完成注册登录,展示列表,CURD 但是版本好像旧了,今天想写一个简单的API 供移动端调用 1.下载最新的node https://nodejs.org/zh- ...

  5. 用原生js来写一个swiper滑块插件

        是不是有点印象了,没错,他的最基本的用法就是左右滑动,插件使用者只需要写几行简单的html和js即可实现一个简单滑动效果,不过你完全可以组合各种元素来适应不同的场景. 当然插件我已经写好了,咱 ...

  6. 大前端工程化之写一个简单的webpack插件

    今天写一个简单的webpack插件,来学习一下webpack插件 webpack插件机制可以使开发者在webpack构建过程中加入自己的行为,来针对自己项目中的一些需求做一些定制化 首先我们得知道一个 ...

  7. 手把手教你从零写一个简单的 VUE--模板篇

    教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...

  8. 从0开始写一个简单的vite hmr 插件

    从0开始写一个简单的vite hmr 插件 0. 写在前面 在构建前端项目的时候,除开基本的资源格式(图片,json)以外,还常常会需要导入一些其他格式的资源,这些资源如果没有第三方vite插件的支持 ...

  9. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

随机推荐

  1. 纯css画直角三角形

    所有的三角形,都是通过盒子模型来设定. border(边框)的不同大小来决定 border-width: 边框的宽度 border-style: 边框的样式 border-color: 边框的颜色 1 ...

  2. pandas导入导出数据-【老鱼学pandas】

    pandas可以读写如下格式的数据类型: 具体详见:http://pandas.pydata.org/pandas-docs/version/0.20/io.html 读取csv文件 我们准备了一个c ...

  3. Centos系统中彻底删除Mysql数据库

    步骤: 1.输入命令查询系统中已安装的mysql. rpm -qa |grep -i mysql 2.逐个卸载mysql. yum remove 系统显示已安装的mysql 比如:yum remove ...

  4. ajax 函数回调

    var initTaxPriod = function (taxNo) { intitSearch(); $("#taxPeriod").html(""); t ...

  5. json,HTTP协议

    JSON 语法规则 JSON 语法是 JavaScript 对象表示语法的子集. 数据在名称/值对中 数据由逗号分隔 大括号保存对象 中括号保存数组 JSON 对象 JSON 对象使用在大括号({}) ...

  6. BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)

    题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...

  7. python性能:不要使用 key in list 判断key是否在list里

    原文:https://docs.quantifiedcode.com/python-anti-patterns/performance/using_key_in_list_to_check_if_ke ...

  8. 06-JDBC

    JDBC > JAVA Database Connectivity java 数据库连接 * 为什么会出现JDBC > SUN公司提供的一种数据库访问规则.规范, 由于数据库种类较多,并且 ...

  9. Python的numpy库中rand(),randn(),randint(),random_integers()的使用

    1.numpy.random.rand() 用法是:numpy.random.rand(d0,d1,…dn) 以给定的形状创建一个数组,并在数组中加入在[0,1]之间均匀分布的随机样本. 用法及实现: ...

  10. __x__(20)0907第四天__列表ul,ol,dl

    列表分为: 有序列表 ul: <ul type="disc"> <li>张三</li> <li>李四</li> < ...