限制滚动到内容区域
Limit Scrolling to Content Area
问题:
我无法将滚动限制在典型 Vue 3 SPA 的内容区域(滚动条不应延伸到页眉和页脚区域)。页眉和页脚块与 Bootstrap fixed-top
和 fixed-bottom
类 一起放置。在所附图片中有点难以看到,但当前内容区域延伸到页眉和页脚后面。页眉和页脚是从 Bootstrap 组件库构建的。我可以使用填充修复内容可见性,但这并不能解决溢出(滚动条)问题。
采取的行动
对于类似的问题,我尝试了很多解决方案,但这些解决方案通常适用于早期版本的 Vue 和 Bootstrap,但似乎对我不起作用。我能够在 vanilla html 和 Bootstrap 中生成我想要的布局——似乎是 Vue 3 注入过程让我感到困惑。我已经尝试将布局应用于 index.html 和 App.vue 但没有成功(同时尝试 Bootstrap 类 和香草 css)。 Bootstrap 依赖项似乎工作正常,所以我认为这不是问题所在(Bootstrap 5 而不是 Bootstrap-Vue)。
期望的结果:
限制滚动到内容区域,同时保持页眉和页脚导航栏固定在它们的位置(并且始终可见)。
环境
代码片段用于提高可读性(不会 运行 到位)。以下代码已删除所有(或几乎所有)放置尝试,因为它们不起作用。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="../public/favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- <script>window.scrollTo(0,1) // this is meant to hide the address bar in mobile Safari on page load.</script>-->
</head>
<body>
<noscript>
<strong>The <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files are auto injected here -->
</body>
</html>
App.vue
<template>
<div id="wrapper" class="m-1">
<div id="header_area">
<Header/>
</div>
<div id="content_area">
<span class="page-title">{{ title }}</span>
<hr class="border-secondary">
<span class="page-content">{{ content }}</span>
<router-view @page-data="updatePageName($event)"/>
</div>
<div id="footer_area">
<Footer/>
</div>
</div>
</template>
<script>
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
export default {
data() {
return {
title: "home",
content: ""
}
},
components: {
Header,
Footer,
},
methods: {
updatePageName: function(event) {
this.title = event.title;
this.content = event.content;
}
}
};
</script>
<style>
@import'~bootstrap/dist/css/bootstrap.css';
@import "./assets/main.css";
</style>
Header.vue(部分)
<template>
<div>
<nav class="Header navbar navbar-expand-sm navbar-dark bg-dark border-bottom border-4 fixed-top" aria-label="Header Bar">
<div class="container-fluid">
<router-link to="/"><span class="navbar-brand">brand</span> </router-link>
<button class="navbar-toggler btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#Navbar" aria-controls="Navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="Navbar">
<ul class="navbar-nav me-auto mb-2 mb-sm-0">
<li class="nav-item dropdown">
<router-link to=""><a class="nav-link dropdown-toggle" id="dropdown01" data-bs-toggle="dropdown" aria-expanded="false">pages</a></router-link>
<ul class="dropdown-menu bg-dark" aria-labelledby="dropdown01" id="dave">
[snip]
main.css
@charset "utf-8";
@font-face {
font-family: 'Lato-Light';
src: local('Lato-Light'), url('Lato-Light.ttf') format("truetype");
}
:root {
--background: #191919;
--dark: #000000;
--grey1: #111111;
--grey2: #222222;
--grey3: #333333;
--grey4: #444444;
--grey5: #555555;
--grey6: #666666;
--grey7: #777777;
--grey8: #888888;
--grey9: #999999;
--light: #FFFFFF;
}
html, body {
background-color: var(--dark) !important;
color: var(--light) !important;
}
a {
color: var(--bs-secondary) !important;
text-decoration: none;
}
body {
font-family: Lato-Light, sans-serif;
font-size: 0.9em;
}
button {
padding: 1px;
}
input {
border: solid 1px var(--grey9);
border-radius: 5px;
box-sizing: border-box;
padding: 5px;
}
li {
float: left;
margin: 0 5px;
padding: 0 2px;
text-align: start;
}
ul {
list-style-type: none;
padding: 0;
}
.dropdown-item {
border: solid 1px var(--bs-dark);
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem;*/
width: 94%;
}
.dropdown-item:hover {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-secondary);
border-radius: 5px;
width: 94%;
}
.dropdown-menu {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-dark) !important;
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem !important;*/
}
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
border: solid 1px var(--bs-dark) !important;
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem !important;*/
left: 100%;
top: 0;
}
.dropdown-toggle::after {
display: none;
}
.navbar {
border-bottom-color: var(--dark) !important;
border-top-color: var(--dark) !important;
margin-bottom: 0;
}
.navbar-brand {
border: solid 1px var(--bs-dark);
border-radius: 5px;
color: var(--bs-secondary) !important;
padding: 5px;
}
.navbar-brand:hover {
border: solid 1px var(--bs-secondary);
border-radius: 5px;
}
.nav-link {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-dark);
border-radius: 5px;
color: var(--bs-secondary) !important;
}
.nav-link:hover {
border: solid 1px var(--bs-secondary);
border-radius: 5px;
}
.nav-link.dropdown-toggle {
padding: 8px;
}
.navbar-nav li:hover > ul.dropdown-menu {
border: solid 1px var(--grey5) !important;
color: var(--bs-secondary) !Important;
display: block;
}
.page-title {
color: var(--grey5);
font-size: 2rem !important;
text-align: left !important;
}
.page-content {
}
.selected {
border-color: lime !important;
}
#app {
}
#header_area {
}
#content_area {
}
#footer_area {
}
#Footer {
font-size: 0.9em;
}
:focus {
border-color: var(--dark);
box-shadow: none;
outline: none;
}
这就是我如何使 CSS 网格规范起作用的方法。 对于我的情况,在 index.html
中向 <html>
和 <body>
添加样式很重要, 但可能不是必需的。可能也不需要将 !Important
分配给网格元素,但这样做是为了保险起见。
现在,由 Vue 路由器注入的任何内容都会出现在 content_area
中,并且 只有 该部分会滚动(根据需要)。
App.vue
<template>
<div class="app m-1">
<div id="header_area">
<Header/>
</div>
<div id="content_area">
<span class="page-title">{{ title }}</span>
<hr class="border-secondary">
<span class="page-content">{{ content }}</span>
<router-view @page-data="updatePageName($event)"/>
</div>
<div id="footer_area">
<Footer/>
</div>
</div>
</template>
<script>
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
export default {
data() {
return {
title: "home",
content: ""
}
},
components: {
Header,
Footer,
},
methods: {
updatePageName: function(event) {
this.title = event.title;
this.content = event.content;
}
}
};
</script>
<style>
@import'~bootstrap/dist/css/bootstrap.css';
@import "./assets/navbar.css";
@import "./assets/main.css";
</style>
index.html
<!DOCTYPE html>
<html lang="en" style="margin: 0;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="../public/favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body style="margin: 0; overflow: hidden;">
<noscript>
<strong>The <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files are auto-injected here -->
</body>
</html>
main.css
.app {
height: 100vh !important;
display: grid !important;
grid-gap: 5px !important;
grid-template-columns: 1fr !important;
grid-template-rows: 65px 1fr 40px !important;
grid-template-areas: "header" "content" "footer" !important;
}
#header_area {
grid-area: header !important;
}
#content_area {
grid-area: content !important;
overflow: auto !important;
}
#footer_area {
grid-area: footer !important;
}
普通HTML示例
body {
background-color: red;
margin: 0;
}
.container {
height: 100vh;
display: grid;
grid-gap: 5px;
grid-template-columns: 1fr;
grid-template-rows: 70px 1fr 40px;
grid-template-areas: "header" "content" "footer";
}
.H {
grid-area: header;
background-color: blue;
color: white;
}
.C {
grid-area: content;
background-color: darkgreen;
color: white;
padding: 15px 5px 10px 5px;
overflow: auto;
}
.F {
grid-area: footer;
background-color: blue;
color: white;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="container">
<div class="H">header</div>
<div class="C">
content
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br>
</div>
<div class="F">footer</div>
</div>
</body>
</html>
问题:
我无法将滚动限制在典型 Vue 3 SPA 的内容区域(滚动条不应延伸到页眉和页脚区域)。页眉和页脚块与 Bootstrap fixed-top
和 fixed-bottom
类 一起放置。在所附图片中有点难以看到,但当前内容区域延伸到页眉和页脚后面。页眉和页脚是从 Bootstrap 组件库构建的。我可以使用填充修复内容可见性,但这并不能解决溢出(滚动条)问题。
采取的行动
对于类似的问题,我尝试了很多解决方案,但这些解决方案通常适用于早期版本的 Vue 和 Bootstrap,但似乎对我不起作用。我能够在 vanilla html 和 Bootstrap 中生成我想要的布局——似乎是 Vue 3 注入过程让我感到困惑。我已经尝试将布局应用于 index.html 和 App.vue 但没有成功(同时尝试 Bootstrap 类 和香草 css)。 Bootstrap 依赖项似乎工作正常,所以我认为这不是问题所在(Bootstrap 5 而不是 Bootstrap-Vue)。
期望的结果:
限制滚动到内容区域,同时保持页眉和页脚导航栏固定在它们的位置(并且始终可见)。
环境
代码片段用于提高可读性(不会 运行 到位)。以下代码已删除所有(或几乎所有)放置尝试,因为它们不起作用。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="../public/favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- <script>window.scrollTo(0,1) // this is meant to hide the address bar in mobile Safari on page load.</script>-->
</head>
<body>
<noscript>
<strong>The <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files are auto injected here -->
</body>
</html>
App.vue
<template>
<div id="wrapper" class="m-1">
<div id="header_area">
<Header/>
</div>
<div id="content_area">
<span class="page-title">{{ title }}</span>
<hr class="border-secondary">
<span class="page-content">{{ content }}</span>
<router-view @page-data="updatePageName($event)"/>
</div>
<div id="footer_area">
<Footer/>
</div>
</div>
</template>
<script>
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
export default {
data() {
return {
title: "home",
content: ""
}
},
components: {
Header,
Footer,
},
methods: {
updatePageName: function(event) {
this.title = event.title;
this.content = event.content;
}
}
};
</script>
<style>
@import'~bootstrap/dist/css/bootstrap.css';
@import "./assets/main.css";
</style>
Header.vue(部分)
<template>
<div>
<nav class="Header navbar navbar-expand-sm navbar-dark bg-dark border-bottom border-4 fixed-top" aria-label="Header Bar">
<div class="container-fluid">
<router-link to="/"><span class="navbar-brand">brand</span> </router-link>
<button class="navbar-toggler btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#Navbar" aria-controls="Navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="Navbar">
<ul class="navbar-nav me-auto mb-2 mb-sm-0">
<li class="nav-item dropdown">
<router-link to=""><a class="nav-link dropdown-toggle" id="dropdown01" data-bs-toggle="dropdown" aria-expanded="false">pages</a></router-link>
<ul class="dropdown-menu bg-dark" aria-labelledby="dropdown01" id="dave">
[snip]
main.css
@charset "utf-8";
@font-face {
font-family: 'Lato-Light';
src: local('Lato-Light'), url('Lato-Light.ttf') format("truetype");
}
:root {
--background: #191919;
--dark: #000000;
--grey1: #111111;
--grey2: #222222;
--grey3: #333333;
--grey4: #444444;
--grey5: #555555;
--grey6: #666666;
--grey7: #777777;
--grey8: #888888;
--grey9: #999999;
--light: #FFFFFF;
}
html, body {
background-color: var(--dark) !important;
color: var(--light) !important;
}
a {
color: var(--bs-secondary) !important;
text-decoration: none;
}
body {
font-family: Lato-Light, sans-serif;
font-size: 0.9em;
}
button {
padding: 1px;
}
input {
border: solid 1px var(--grey9);
border-radius: 5px;
box-sizing: border-box;
padding: 5px;
}
li {
float: left;
margin: 0 5px;
padding: 0 2px;
text-align: start;
}
ul {
list-style-type: none;
padding: 0;
}
.dropdown-item {
border: solid 1px var(--bs-dark);
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem;*/
width: 94%;
}
.dropdown-item:hover {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-secondary);
border-radius: 5px;
width: 94%;
}
.dropdown-menu {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-dark) !important;
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem !important;*/
}
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
border: solid 1px var(--bs-dark) !important;
color: var(--bs-secondary) !Important;
/*font-size: 0.9rem !important;*/
left: 100%;
top: 0;
}
.dropdown-toggle::after {
display: none;
}
.navbar {
border-bottom-color: var(--dark) !important;
border-top-color: var(--dark) !important;
margin-bottom: 0;
}
.navbar-brand {
border: solid 1px var(--bs-dark);
border-radius: 5px;
color: var(--bs-secondary) !important;
padding: 5px;
}
.navbar-brand:hover {
border: solid 1px var(--bs-secondary);
border-radius: 5px;
}
.nav-link {
background-color: var(--bs-dark) !important;
border: solid 1px var(--bs-dark);
border-radius: 5px;
color: var(--bs-secondary) !important;
}
.nav-link:hover {
border: solid 1px var(--bs-secondary);
border-radius: 5px;
}
.nav-link.dropdown-toggle {
padding: 8px;
}
.navbar-nav li:hover > ul.dropdown-menu {
border: solid 1px var(--grey5) !important;
color: var(--bs-secondary) !Important;
display: block;
}
.page-title {
color: var(--grey5);
font-size: 2rem !important;
text-align: left !important;
}
.page-content {
}
.selected {
border-color: lime !important;
}
#app {
}
#header_area {
}
#content_area {
}
#footer_area {
}
#Footer {
font-size: 0.9em;
}
:focus {
border-color: var(--dark);
box-shadow: none;
outline: none;
}
这就是我如何使 CSS 网格规范起作用的方法。 对于我的情况,在 index.html
中向 <html>
和 <body>
添加样式很重要, 但可能不是必需的。可能也不需要将 !Important
分配给网格元素,但这样做是为了保险起见。
现在,由 Vue 路由器注入的任何内容都会出现在 content_area
中,并且 只有 该部分会滚动(根据需要)。
App.vue
<template>
<div class="app m-1">
<div id="header_area">
<Header/>
</div>
<div id="content_area">
<span class="page-title">{{ title }}</span>
<hr class="border-secondary">
<span class="page-content">{{ content }}</span>
<router-view @page-data="updatePageName($event)"/>
</div>
<div id="footer_area">
<Footer/>
</div>
</div>
</template>
<script>
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
export default {
data() {
return {
title: "home",
content: ""
}
},
components: {
Header,
Footer,
},
methods: {
updatePageName: function(event) {
this.title = event.title;
this.content = event.content;
}
}
};
</script>
<style>
@import'~bootstrap/dist/css/bootstrap.css';
@import "./assets/navbar.css";
@import "./assets/main.css";
</style>
index.html
<!DOCTYPE html>
<html lang="en" style="margin: 0;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="../public/favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body style="margin: 0; overflow: hidden;">
<noscript>
<strong>The <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files are auto-injected here -->
</body>
</html>
main.css
.app {
height: 100vh !important;
display: grid !important;
grid-gap: 5px !important;
grid-template-columns: 1fr !important;
grid-template-rows: 65px 1fr 40px !important;
grid-template-areas: "header" "content" "footer" !important;
}
#header_area {
grid-area: header !important;
}
#content_area {
grid-area: content !important;
overflow: auto !important;
}
#footer_area {
grid-area: footer !important;
}
普通HTML示例
body {
background-color: red;
margin: 0;
}
.container {
height: 100vh;
display: grid;
grid-gap: 5px;
grid-template-columns: 1fr;
grid-template-rows: 70px 1fr 40px;
grid-template-areas: "header" "content" "footer";
}
.H {
grid-area: header;
background-color: blue;
color: white;
}
.C {
grid-area: content;
background-color: darkgreen;
color: white;
padding: 15px 5px 10px 5px;
overflow: auto;
}
.F {
grid-area: footer;
background-color: blue;
color: white;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="container">
<div class="H">header</div>
<div class="C">
content
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br> .
<br>
</div>
<div class="F">footer</div>
</div>
</body>
</html>