template html & css
This commit is contained in:
185
panel_resize.html
Normal file
185
panel_resize.html
Normal file
@@ -0,0 +1,185 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Page une-colonne redimensionnable</title>
|
||||
<style>
|
||||
:root{
|
||||
--min-panel: 40px;
|
||||
--handle-size: 8px;
|
||||
--bg-top: #2b6cb0;
|
||||
--bg-middle: #edf2f7;
|
||||
--bg-bottom: #2f855a;
|
||||
}
|
||||
|
||||
html,body{height:100%;margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,'Helvetica Neue',Arial}
|
||||
body{display:flex;align-items:center;justify-content:center;background:#f7fafc;padding:18px}
|
||||
|
||||
/* zone redimensionnable globale (vous pouvez la glisser depuis le coin) */
|
||||
#app{
|
||||
width:900px;
|
||||
height:600px;
|
||||
max-width:100%;
|
||||
max-height:100%;
|
||||
background:#fff;
|
||||
box-shadow:0 8px 30px rgba(2,6,23,.12);
|
||||
border-radius:10px;
|
||||
overflow:hidden; /* les panneaux gèrent leur propre overflow */
|
||||
resize:both; /* autorise redimension globale par coin */
|
||||
display:flex;
|
||||
flex-direction:column;
|
||||
}
|
||||
|
||||
/* panneaux */
|
||||
.panel{
|
||||
min-height:var(--min-panel);
|
||||
overflow:auto;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
padding:14px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
|
||||
header{background:var(--bg-top);color:#fff}
|
||||
main{background:var(--bg-middle);color:#1a202c;flex:1}
|
||||
footer{background:var(--bg-bottom);color:#fff}
|
||||
|
||||
/* handle horizontal (séparateur entre panneaux) */
|
||||
.resizer{
|
||||
height:var(--handle-size);
|
||||
background:linear-gradient(90deg, rgba(0,0,0,0.08), rgba(0,0,0,0.02));
|
||||
cursor:row-resize;
|
||||
position:relative;
|
||||
z-index:10;
|
||||
}
|
||||
.resizer::after{
|
||||
content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
|
||||
width:40px;height:4px;border-radius:4px;background:rgba(0,0,0,0.12)
|
||||
}
|
||||
|
||||
/* petits controles d'aide */
|
||||
.hint{font-size:13px;opacity:.9}
|
||||
.controls{position:absolute;right:10px;top:8px;font-size:12px}
|
||||
.panel .title{font-weight:700}
|
||||
|
||||
/* styles adaptatifs pour petits écrans */
|
||||
@media (max-width:520px){
|
||||
#app{width:100%;height:80vh;border-radius:6px}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" role="application">
|
||||
<header class="panel" id="topPanel" style="height:120px;">
|
||||
<div>
|
||||
<div class="title">Bandeau du haut</div>
|
||||
<div class="hint">Glissez la barre grise sous ce bandeau pour redimensionner verticalement.</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="resizer" data-target="top"></div>
|
||||
|
||||
<main class="panel" id="centerPanel" style="height:calc(100% - 240px);">
|
||||
<div>
|
||||
<div class="title">Conteneur central</div>
|
||||
<div class="hint">Ce conteneur prend l'espace restant. Vous pouvez aussi redimensionner la fenêtre par le coin (resize).</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="resizer" data-target="bottom"></div>
|
||||
|
||||
<footer class="panel" id="bottomPanel" style="height:120px;">
|
||||
<div>
|
||||
<div class="title">Bandeau du bas</div>
|
||||
<div class="hint">Glissez la barre grise au-dessus pour modifier sa hauteur.</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Gestion du drag pour les séparateurs horizontaux
|
||||
(function(){
|
||||
const app = document.getElementById('app');
|
||||
const topPanel = document.getElementById('topPanel');
|
||||
const centerPanel = document.getElementById('centerPanel');
|
||||
const bottomPanel = document.getElementById('bottomPanel');
|
||||
const min = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--min-panel')) || 40;
|
||||
|
||||
let dragging = null;
|
||||
let startY = 0;
|
||||
let startTopH = 0;
|
||||
let startBottomH = 0;
|
||||
|
||||
function onDown(e){
|
||||
e.preventDefault();
|
||||
dragging = this.getAttribute('data-target');
|
||||
startY = e.touches ? e.touches[0].clientY : e.clientY;
|
||||
startTopH = topPanel.getBoundingClientRect().height;
|
||||
startBottomH = bottomPanel.getBoundingClientRect().height;
|
||||
document.addEventListener('mousemove', onMove);
|
||||
document.addEventListener('mouseup', onUp);
|
||||
document.addEventListener('touchmove', onMove, {passive:false});
|
||||
document.addEventListener('touchend', onUp);
|
||||
app.style.userSelect = 'none';
|
||||
}
|
||||
|
||||
function onMove(e){
|
||||
if(!dragging) return;
|
||||
e.preventDefault();
|
||||
const y = e.touches ? e.touches[0].clientY : e.clientY;
|
||||
const dy = y - startY;
|
||||
|
||||
if(dragging === 'top'){
|
||||
// modifier hauteur top et center
|
||||
let newTop = startTopH + dy;
|
||||
let newCenter = centerPanel.getBoundingClientRect().height - dy;
|
||||
|
||||
if(newTop < min) newTop = min;
|
||||
if(newCenter < min) newTop = startTopH + (centerPanel.getBoundingClientRect().height - min);
|
||||
|
||||
topPanel.style.height = newTop + 'px';
|
||||
} else if(dragging === 'bottom'){
|
||||
// modifier hauteur bottom et center inversé
|
||||
let newBottom = startBottomH - dy; // parce que on déplace la ligne entre center et bottom
|
||||
let newCenter = centerPanel.getBoundingClientRect().height + dy;
|
||||
|
||||
if(newBottom < min) newBottom = min;
|
||||
if(newCenter < min) newBottom = startBottomH + (centerPanel.getBoundingClientRect().height - min);
|
||||
|
||||
bottomPanel.style.height = newBottom + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function onUp(){
|
||||
dragging = null;
|
||||
document.removeEventListener('mousemove', onMove);
|
||||
document.removeEventListener('mouseup', onUp);
|
||||
document.removeEventListener('touchmove', onMove);
|
||||
document.removeEventListener('touchend', onUp);
|
||||
app.style.userSelect = '';
|
||||
}
|
||||
|
||||
document.querySelectorAll('.resizer').forEach(r => {
|
||||
r.addEventListener('mousedown', onDown);
|
||||
r.addEventListener('touchstart', onDown, {passive:false});
|
||||
});
|
||||
|
||||
// Ajuster le panneau central automatiquement quand on redimensionne la boîte globale
|
||||
const ro = new ResizeObserver(() => {
|
||||
// calculer la hauteur restante pour center
|
||||
const total = app.clientHeight;
|
||||
const topH = topPanel.getBoundingClientRect().height;
|
||||
const bottomH = bottomPanel.getBoundingClientRect().height;
|
||||
const centerH = Math.max(min, total - topH - bottomH - 2 * parseInt(getComputedStyle(document.documentElement).getPropertyValue('--handle-size')));
|
||||
centerPanel.style.height = centerH + 'px';
|
||||
});
|
||||
ro.observe(app);
|
||||
|
||||
// initialisation (force le calcul)
|
||||
window.addEventListener('load', () => { ro.takeRecords(); });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user