Est-ce que quelqu'un connaît une bonne technique pour faire un volet divisé redimensionnable en HTML?
Peut-on utiliser css/jquery/javascript ou quelqu'un connaît-il une bonne bibliothèque javascript qu'ils ont utilisée?
(Un exemple de volet divisé est la barre de favoris dans Internet Explorer que vous avez peut-être ancrée à gauche de la fenêtre de votre navigateur principal)
Il y a sûrement beaucoup d'implémentations déjà. Heres one: http://layout.jquery-dev.com/ démontré ici: http://layout.jquery-dev.com/demos/simple.html Et le code source ici: https://github.com/allpro/layout/
Je voulais une version légère de Vanilla (jQuery UI Layout pèse 185 ko), aucune option de dépendance (toutes les bibliothèques existantes nécessitent jQuery). J'ai donc écrit Split.js .
Il pèse moins de 2 Ko et ne nécessite aucun balisage spécial. Il prend en charge les anciens navigateurs vers IE9 (ou IE8 avec polyfill). Pour les navigateurs modernes, vous pouvez l'utiliser avec les dispositions Flexbox et Grid.
Voici mon approche légère de Vanilla js, en utilisant flexbox:
http://codepen.io/lingtalfi/pen/zoNeJp
Testé avec succès en chrome 54, Firefox 50, Safari 10, je ne connais pas les autres navigateurs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.rawgit.com/lingtalfi/simpledrag/master/simpledrag.js"></script>
<style type="text/css">
html, body {
height: 100%;
}
.panes-container {
display: flex;
width: 100%;
overflow: hidden;
}
.left-pane {
width: 18%;
background: #ccc;
}
.panes-separator {
width: 2%;
background: red;
position: relative;
cursor: col-resize;
}
.right-pane {
flex: auto;
background: #eee;
}
.panes-container,
.panes-separator,
.left-pane,
.right-pane {
margin: 0;
padding: 0;
height: 100%;
}
</style>
</head>
<body>
<div class="panes-container">
<div class="left-pane" id="left-pane">
<p>I'm the left pane</p>
<ul>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
</ul>
</div>
<div class="panes-separator" id="panes-separator"></div>
<div class="right-pane" id="right-pane">
<p>And I'm the right pane</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A accusantium at cum cupiditate dolorum, eius eum
eveniet facilis illum maiores molestiae necessitatibus optio possimus sequi sunt, vel voluptate. Asperiores,
voluptate!
</p>
</div>
</div>
<script>
var leftPane = document.getElementById('left-pane');
var rightPane = document.getElementById('right-pane');
var paneSep = document.getElementById('panes-separator');
// The script below constrains the target to move horizontally between a left and a right virtual boundaries.
// - the left limit is positioned at 10% of the screen width
// - the right limit is positioned at 90% of the screen width
var leftLimit = 10;
var rightLimit = 90;
paneSep.sdrag(function (el, pageX, startX, pageY, startY, fix) {
fix.skipX = true;
if (pageX < window.innerWidth * leftLimit / 100) {
pageX = window.innerWidth * leftLimit / 100;
fix.pageX = pageX;
}
if (pageX > window.innerWidth * rightLimit / 100) {
pageX = window.innerWidth * rightLimit / 100;
fix.pageX = pageX;
}
var cur = pageX / window.innerWidth * 100;
if (cur < 0) {
cur = 0;
}
if (cur > window.innerWidth) {
cur = window.innerWidth;
}
var right = (100-cur-2);
leftPane.style.width = cur + '%';
rightPane.style.width = right + '%';
}, null, 'horizontal');
</script>
</body>
</html>
Ce code html dépend de la bibliothèque légère simpledrag Vanilla js (moins de 60 lignes de code).
Auparavant, vous utilisiez des cadres pour y parvenir. Il y a plusieurs raisons pour lesquelles cette approche n'est pas si bonne. Voir la réponse de Reece à pourquoi les cadres sont mauvais . Voir aussi Jakob Nielson/ Pourquoi Frames Suck (la plupart du temps)
Une approche un peu plus récente consiste à utiliser des cadres en ligne. Cela a aussi des avantages et des inconvénients: Les iframes sont-ils considérés comme des "mauvaises pratiques"?
Une approche encore meilleure consiste à utiliser positionnement fixe. En plaçant le contenu de navigation (par exemple, les liens des favoris dans votre exemple) dans un élément de bloc (comme un div
), appliquez position:fixed
à cet élément et définissez les propriétés left, top et bottom comme ceci:
#myNav {
position:fixed;
left:0px;
top:0px;
bottom:0px;
width:200px;
}
... vous obtiendrez une colonne verticale sur le côté gauche de la page qui ne bougera pas lorsque l'utilisateur fera défiler la page.
Le reste du contenu de la page ne "sentira" pas la présence de cet élément de navigation, il doit donc prendre en compte les 200 pixels d'espace qu'il occupe. Vous pouvez le faire en plaçant le reste du contenu dans une autre div et en paramétrant margin-left:200px;
.
Améliorer la réponse de Reza:
<html><head><style>
.splitter {
width: 100%;
height: 100px;
display: flex;
}
#separator {
cursor: col-resize;
background-color: #aaa;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='30'><path d='M2 0 v30 M5 0 v30 M8 0 v30' fill='none' stroke='black'/></svg>");
background-repeat: no-repeat;
background-position: center;
width: 10px;
height: 100%;
/* prevent browser's built-in drag from interfering */
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#first {
background-color: #dde;
width: 20%;
height: 100%;
min-width: 10px;
}
#second {
background-color: #eee;
width: 80%;
height: 100%;
min-width: 10px;
}
</style></head><body>
<div class="splitter">
<div id="first"></div>
<div id="separator" ></div>
<div id="second" ></div>
</div>
<script>
// function is used for dragging and moving
function dragElement( element, direction)
{
var md; // remember mouse down info
const first = document.getElementById("first");
const second = document.getElementById("second");
element.onmousedown = onMouseDown;
function onMouseDown( e )
{
//console.log("mouse down: " + e.clientX);
md = {e,
offsetLeft: element.offsetLeft,
offsetTop: element.offsetTop,
firstWidth: first.offsetWidth,
secondWidth: second.offsetWidth};
document.onmousemove = onMouseMove;
document.onmouseup = () => {
//console.log("mouse up");
document.onmousemove = document.onmouseup = null;
}
}
function onMouseMove( e )
{
//console.log("mouse move: " + e.clientX);
var delta = {x: e.clientX - md.e.x,
y: e.clientY - md.e.y};
if (direction === "H" ) // Horizontal
{
// prevent negative-sized elements
delta.x = Math.min(Math.max(delta.x, -md.firstWidth),
md.secondWidth);
element.style.left = md.offsetLeft + delta.x + "px";
first.style.width = (md.firstWidth + delta.x) + "px";
second.style.width = (md.secondWidth - delta.x) + "px";
}
}
}
dragElement( document.getElementById("separator"), "H" );
</script></body></html>
Hmm je suis tombé sur cette propriété en CSS3 . Cela pourrait être plus facile à utiliser . https://www.w3schools.com/cssref/css3_pr_resize.asp
J'ai écrit un code simple pour cela sans aucune bibliothèque tierce; Ce code est seulement pour le séparateur horizontal (vertical est le même)
function onload()
{
dragElement( document.getElementById("seperator"), "H" );
}
// function is used for dragging and moving
function dragElement( element, direction, handler )
{
// Two variables for tracking positions of the cursor
const drag = { x : 0, y : 0 };
const delta = { x : 0, y : 0 };
/* if present, the handler is where you move the DIV from
otherwise, move the DIV from anywhere inside the DIV */
handler ? ( handler.onmousedown = dragMouseDown ): ( element.onmousedown = dragMouseDown );
// function that will be called whenever the down event of the mouse is raised
function dragMouseDown( e )
{
drag.x = e.clientX;
drag.y = e.clientY;
document.onmousemove = onMouseMove;
document.onmouseup = () => { document.onmousemove = document.onmouseup = null; }
}
// function that will be called whenever the up event of the mouse is raised
function onMouseMove( e )
{
const currentX = e.clientX;
const currentY = e.clientY;
delta.x = currentX - drag.x;
delta.y = currentY - drag.y;
const offsetLeft = element.offsetLeft;
const offsetTop = element.offsetTop;
const first = document.getElementById("first");
const second = document.getElementById("second");
let firstWidth = first.offsetWidth;
let secondWidth = second.offsetWidth;
if (direction === "H" ) // Horizontal
{
element.style.left = offsetLeft + delta.x + "px";
firstWidth += delta.x;
secondWidth -= delta.x;
}
drag.x = currentX;
drag.y = currentY;
first.style.width = firstWidth + "px";
second.style.width = secondWidth + "px";
}
}
.splitter {
width: 500px;
height: 100px;
display: flex;
}
#seperator {
cursor: col-resize;
background: url(https://raw.githubusercontent.com/RickStrahl/jquery-resizable/master/assets/vsizegrip.png) center center no-repeat #535353;
width: 10px;
height: 100px;
min-width: 10px;
}
#first {
background-color: green;
width: 100px;
height: 100px;
min-width: 10px;
}
#second {
background-color: red;
width: 390px;
height: 100px;
min-width: 10px;
}
<html>
<head>
<link rel="stylesheet" href="T10-Splitter.css">
<script src="T10-Splitter.js"></script>
</head>
<body onload="onload()">
<div class="splitter">
<div id="first"></div>
<div id="seperator"></div>
<div id="second"></div>
</div>
</body>
</html>
Une approche totalement différente consiste à mettre des éléments dans une grille, telle que la grille ui ou la grille de Kendo, et à redimensionner les colonnes. Un inconvénient est que les utilisateurs ne pourraient pas redimensionner les lignes, bien que la taille des lignes puisse être définie par programme.
Vous pouvez utiliser le positionnement absolu ou absolu. Ce CSS, par exemple, ancrera une barre de 2em sur le côté gauche de votre page:
body {
padding-left: 2.5em;
}
body > #bar {
position:fixed;
top:0; left:0;
width: 2em;
height: 100%;
border-right: 2px solid #55F; background: #ddd;
}
Avez-vous essayé la bibliothèque Dave Methwin, http://methvin.com/splitter/
Vous pouvez le faire avec JqueryUI sans une autre bibliothèque JS. Ajoutez simplement une fonction à l’événement .resizable
resize pour ajuster la largeur de l’autre div.
$("#left_pane").resizable({
handles: 'e', // 'East' side of div draggable
resize: function() {
$("#right_pane").outerWidth( $("#container").innerWidth() - $("#left_pane").outerWidth() );
}
});
Voici l'intégrale JS Fiddle .
J'ai trouvé splitter/ http://www.dreamchain.com/split-pane/ qui fonctionne avec jquery v1.9
. Remarque Je devais ajouter le code CSS suivant pour le faire fonctionner avec la barre de navigation bootstrap
corrigée.
fixed-left {
position: absolute !important; /* to override relative */
height: auto !important;
top: 55px; /* fixed navbar height */
bottom: 0px;
}
Accordéon le plus simple, avec juste redimensionnement css . La règle débordement doit également être définie.
div {
resize: vertical;
overflow: auto;
border: 1px solid
}
.menu {
display: grid
/* Try height: 100% or height: 100vh */
}
<div class="menu">
<div>
Hello world!
</div>
<div>
Hello world!
</div>
<div>
Hello world!
</div>
<div>
Hello world!
</div>
<div>
Hello world!
</div>
<div>
Hello world!
</div>
</div>
Vitres redimensionnables verticalement les plus simples:
div {
resize: horizontal;
overflow: auto;
border: 1px solid;
display: inline-flex;
height:90vh
}
<div>
Hello world!
</div>
<div>
Hello world!
</div>
Une bonne bibliothèque est Shield UI - vous pouvez jeter un oeil à leur flexible Splitter widget et au reste des composants puissants offerts par le framework.