'Best practice for lazy loading large nested lists into webpage (browser crashing)
I have a webpage that displays our database schema in a bootstrap card similar to how workbench shows the schema in their navigator. The problem is that we have over 3000 tables and 15x that in columns. This makes the webpage freeze when the user tries to use the search feature and while the elements are loaded when they click the schema.
goal: Create a scrollable schema navigator that uses lazy loading and does not crash the browser when the user attempts a search.
How I am getting the data: The current method I am using is a JSON document that is being transformed via php and loaded with ajax. I was thinking about possibly generating and storing the raw html of the list and cutting out the php processing all together. I do have complete control of how this data is formatted pre load.
Load Method: I have three separate php files.
- Loads the list of available schemas based on users pick.
- on schema selection, load the available tables.
- on table select load the available columns.
This method works well as some users do not use the schema navigation feature, but does crash quite often when trying to filter thru the objects.
Alternative load method I've tried:
Instead of dealing with an json file, I generate the raw html and load that in.
.container {
content-visibility: auto;
overflow-y: scroll;
height: 500px;
}
.tree {
--spacing: 1.5rem;
--radius: 10px;
}
.tree li {
display: block;
position: relative;
padding-left: calc(2 * var(--spacing) - var(--radius) - 2px);
}
.tree ul {
margin-left: calc(var(--radius) - var(--spacing));
padding-left: 0;
}
.tree ul li {
border-left: 2px solid #ddd;
}
.tree ul li:last-child {
border-color: transparent;
}
.tree ul li::before {
content: '';
display: block;
position: absolute;
top: calc(var(--spacing) / -2);
left: -2px;
width: calc(var(--spacing) + 2px);
height: calc(var(--spacing) + 1px);
border: solid #ddd;
border-width: 0 0 2px 2px;
}
.tree summary {
display: block;
cursor: pointer;
}
.tree summary::marker,
.tree summary::-webkit-details-marker {
display: none;
}
.tree summary:focus {
outline: none;
}
.tree summary:focus-visible {
outline: 1px dotted #000;
}
.tree li::after,
.tree summary::before {
content: '';
display: block;
position: absolute;
top: calc(var(--spacing) / 2 - var(--radius));
left: calc(var(--spacing) - var(--radius) - 1px);
width: calc(2 * var(--radius));
height: calc(2 * var(--radius));
border-radius: 50%;
background: #ddd;
}
.tree summary::before {
content: '+';
z-index: 1;
background: #696;
color: #fff;
line-height: calc(2 * var(--radius) - 2px);
text-align: center;
}
.tree details[open]>summary::before {
content: '-';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="col-md-3">
<div class="card">
<div class="card-body bg-light">
<p id="sideBarText" class="d-none">Table Information will populate after an environment and a database have been selected.
</p>
<div id="schemaTables" class="row schemaTables" style="display: block;">
<div id="sideBar-info">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">DEV</li>
<li class="breadcrumb-item active" aria-current="page">World</li>
</ol>
</nav>
</div>
<input id="searchTables" type="text" placeholder="Filter.." style="width:100%">
<div id="sideBar-tables" class="container">
<ul class="tree">
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>city</summary>
<ul>
<li>ID</li>
<li>Name</li>
<li>CountryCode</li>
<li>District</li>
<li>Population</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>country</summary>
<ul>
<li>Code</li>
<li>Name</li>
<li>Continent</li>
<li>Region</li>
<li>SurfaceArea</li>
<li>IndepYear</li>
<li>Population</li>
<li>LifeExpectancy</li>
<li>GNP</li>
<li>GNPOld</li>
<li>LocalName</li>
<li>GovernmentForm</li>
<li>HeadOfState</li>
<li>Capital</li>
<li>Code2</li>
</ul>
</details>
</li>
<li>
<details close>
<summary>countrylanguage</summary>
<ul>
<li>CountryCode</li>
<li>Language</li>
<li>IsOfficial</li>
<li>Percentage</li>
</ul>
</details>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
I have tried adding the content-visibility: auto and overflow-y: scroll properties but it seems that I am just asking too much of the browser.
I cannot find a clear guide on how to lazy load html elements that are not images as the user scrolls.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

