J'ai 2 boîtes et une ligne de div verticale dans un div de conteneur unique (code et violon ci-dessous).
J'utilise des grilles CSS pour positionner mes éléments à l'intérieur du conteneur
Ce que j'aimerais accomplir, c'est utiliser la ligne verticale pour redimensionner horizontalement les deux cases en fonction de la position de la ligne verticale.
Je m'excuse si la question est noobish, je suis nouveau dans le développement web, utilisé uniquement Python auparavant, j'ai déjà essayé de rechercher Google et stackoverflow mais toutes les solutions semblent trop compliquées et nécessitent généralement des bibliothèques supplémentaires, j'étais à la recherche de quelque chose de plus simple et de JS uniquement.
HTML:
<div class="wrapper">
<div class="box a">A</div>
<div class="handler"></div>
<div class="box b">B</div>
</div>
CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-template-columns: 200px 8px 200px;
grid-gap: 10px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
resize: both;
}
.handler{
width: 3px;
height: 100%;
padding: 0px 0;
top: 0;
background: red;
draggable: true;
}
Ce que vous avez l'intention de faire peut être fait en utilisant CSS flexbox - il n'est pas nécessaire d'utiliser une grille CSS. La mauvaise nouvelle est que HTML + CSS n'est pas si intelligent que déclarer resize
et draggable
rendra la mise en page flexible et ajustable par interaction avec l'utilisateur. Pour cela, vous devrez utiliser JS. La bonne nouvelle est que ce n'est en fait pas trop compliqué.
Voici une capture d'écran rapide de la sortie du code ci-dessous:
Cependant, pour que vous compreniez le code que je publierai ci-dessous, vous devrez vous familiariser avec:
.addEventListener
. Dans ce cas, nous utiliserons une combinaison de mousedown
, mouseup
et mousemove
pour déterminer si l'utilisateur est en train de faire glisser l'élémentTout d'abord, vous souhaiterez mettre en forme vos boîtes à l'aide de CSS flexbox. Nous déclarons simplement display: flex
sur le parent, puis utilisez flex: 1 1 auto
(ce qui se traduit par "laisser l'élément grandir, laisser l'élément rétrécir et avoir des largeurs égales). Cette disposition n'est valide que lors du rendu initial de la page:
.wrapper {
/* Use flexbox */
display: flex;
}
.box {
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
flex: 1 1 auto;
}
Vous souhaitez écouter les événements de souris qui pourraient provenir de votre .handler
élément, et vous voulez un indicateur global qui se souvienne si l'utilisateur fait glisser ou non:
var handler = document.querySelector('.handler');
var isHandlerDragging = false;
Ensuite, vous pouvez utiliser la logique suivante pour vérifier si l'utilisateur fait glisser ou non:
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
// Set boxA width properly
// [...more logic here...]
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
Il ne vous reste plus qu'à calculer la largeur de la case A (à insérer dans le [...more logic here...]
placeholder dans le code ci-dessus), pour qu'il corresponde à celui du mouvement de la souris. Flexbox s'assurera que la case B remplira l'espace restant:
// Get offset
var containerOffsetLeft = wrapper.offsetLeft;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientX - containerOffsetLeft;
// Resize box A
// * 8px is the left/right spacing between .handler and its inner pseudo-element
// * Set flex-grow to 0 to prevent it from growing
boxA.style.width = (pointerRelativeXpos - 8) + 'px';
boxA.style.flexGrow = 0;
var handler = document.querySelector('.handler');
var wrapper = handler.closest('.wrapper');
var boxA = wrapper.querySelector('.box');
var isHandlerDragging = false;
document.addEventListener('mousedown', function(e) {
// If mousedown event is fired from .handler, toggle flag to true
if (e.target === handler) {
isHandlerDragging = true;
}
});
document.addEventListener('mousemove', function(e) {
// Don't do anything if dragging flag is false
if (!isHandlerDragging) {
return false;
}
// Get offset
var containerOffsetLeft = wrapper.offsetLeft;
// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientX - containerOffsetLeft;
// Arbitrary minimum width set on box A, otherwise its inner content will collapse to width of 0
var boxAminWidth = 60;
// Resize box A
// * 8px is the left/right spacing between .handler and its inner pseudo-element
// * Set flex-grow to 0 to prevent it from growing
boxA.style.width = (Math.max(boxAminWidth, pointerRelativeXpos - 8)) + 'px';
boxA.style.flexGrow = 0;
});
document.addEventListener('mouseup', function(e) {
// Turn off dragging flag when user mouse is up
isHandlerDragging = false;
});
body {
margin: 40px;
}
.wrapper {
background-color: #fff;
color: #444;
/* Use flexbox */
display: flex;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
/* Use box-sizing so that element's outerwidth will match width property */
box-sizing: border-box;
/* Allow box to grow and shrink, and ensure they are all equally sized */
flex: 1 1 auto;
}
.handler {
width: 20px;
padding: 0;
cursor: ew-resize;
flex: 0 0 auto;
}
.handler::before {
content: '';
display: block;
width: 4px;
height: 100%;
background: red;
margin: 0 auto;
}
<div class="wrapper">
<div class="box">A</div>
<div class="handler"></div>
<div class="box">B</div>
</div>
Voici un exemple de gestion des événements de glissement, mais en utilisant des grilles CSS
L'astuce consiste à définir les colonnes (ou lignes) de modèle de grille sur le conteneur de grille plutôt que la taille des éléments de la grille
let isLeftDragging = false;
let isRightDragging = false;
function ResetColumnSizes() {
// when page resizes return to default col sizes
let page = document.getElementById("pageFrame");
page.style.gridTemplateColumns = "2fr 6px 6fr 6px 2fr";
}
function SetCursor(cursor) {
let page = document.getElementById("page");
page.style.cursor = cursor;
}
function StartLeftDrag() {
// console.log("mouse down");
isLeftDragging = true;
SetCursor("ew-resize");
}
function StartRightDrag() {
// console.log("mouse down");
isRightDragging = true;
SetCursor("ew-resize");
}
function EndDrag() {
// console.log("mouse up");
isLeftDragging = false;
isRightDragging = false;
SetCursor("auto");
}
function OnDrag(event) {
if (isLeftDragging || isRightDragging) {
// console.log("Dragging");
//console.log(event);
let page = document.getElementById("page");
let leftcol = document.getElementById("leftcol");
let rightcol = document.getElementById("rightcol");
let leftColWidth = isLeftDragging ? event.clientX : leftcol.clientWidth;
let rightColWidth = isRightDragging ? page.clientWidth - event.clientX : rightcol.clientWidth;
let dragbarWidth = 6;
let cols = [
leftColWidth,
dragbarWidth,
page.clientWidth - (2 * dragbarWidth) - leftColWidth - rightColWidth,
dragbarWidth,
rightColWidth
];
let newColDefn = cols.map(c => c.toString() + "px").join(" ");
// console.log(newColDefn);
page.style.gridTemplateColumns = newColDefn;
event.preventDefault()
}
}
#page {
height: 100%;
background-color: pink;
display: grid;
grid-template-areas: 'header header header header header' 'leftcol leftdragbar tabs tabs tabs' 'leftcol leftdragbar tabpages rightdragbar rightcol' 'leftcol leftdragbar footer footer footer';
grid-template-rows: min-content 1fr 9fr 1fr;
grid-template-columns: 2fr 6px 6fr 6px 2fr;
}
/*****************************/
#header {
background-color: lightblue;
overflow: auto;
grid-area: header;
}
#leftcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: leftcol;
}
#leftdragbar {
background-color: black;
grid-area: leftdragbar;
cursor: ew-resize;
}
#tabs {
background-color: #cccccc;
overflow: auto;
grid-area: tabs;
}
#tabpages {
background-color: #888888;
overflow: auto;
grid-area: tabpages;
}
#rightdragbar {
background-color: black;
grid-area: rightdragbar;
cursor: ew-resize;
}
#rightcol {
background-color: #aaaaaa;
overflow: auto;
grid-area: rightcol;
}
#footer {
background-color: lightblue;
overflow: auto;
grid-area: footer;
}
<body onresize="ResetColumnSizes()">
<div id="page" onmouseup="EndDrag()" onmousemove="OnDrag(event)">
<div id="header">
Header
</div>
<div id="leftcol">
Left Col
</div>
<div id="leftdragbar" onmousedown="StartLeftDrag()"></div>
<div id="tabs">
Tabs
</div>
<div id="tabpages">
Tab Pages
</div>
<div id="rightdragbar" onmousedown="StartRightDrag()"></div>
<div id="rightcol">
Rightcol
</div>
<div id="footer">
Footer
</div>
</div>
</body>