5545 sujets

Sémantique web et HTML

Je suis en train de créer mon petit site web perso et j'utilise le système des iframe pour, avec un menu, appeler le contenu de différentes pages (par exemple, mon menu a les boutons "Carnet de bord", "Projets" et "Sites" et quand on clique sur le premier, l'iframe appelle la page qui correspond au carnet de bord, etc).

Mon souci, c'est que lorsque j'appelle ces pages, la hauteur de l'iframe ne s'adapte pas. Par exemple, pour la page des projets, un scroll apparait pour pouvoir lire tout le contenu de l'iframe. Sauf qu'avec la page qui accueille l'iframe, il y a déjà un scroll et donc ça fait un peu doublon (en plus de pas être pratique).
Ce que je cherche à faire, c'est de ne jamais avoir à scroller l'iframe pour lire tout son contenu, que ce contenu apparaisse toujours entièrement et qu'on ait à scroller la page qui accueille l'iframe au lieu de devoir toujours scroller l'iframe.

J'ai testé ça sur Firefox et Chrome, je tourne sous macOS Mojave et j'utilise Sublime Text 2 pour coder.

Je suis tout juste inscrit ici donc je sais pas trop si je donne assez de détails ou pas, mais je suis dispo pour en apporter si nécessaire.
Je peux lier un CodePen si ça peut aider.

Voici le HTML de mon iframe:

<iframe id="frame" scrolling="yes" src="dernierarticle.html" border="0" frameBorder="NO" height="100%" ></iframe>


Et le CSS:

#frame {
    display: block;
    position: center;
    overflow: hidden;
    width: 1200px;
    height: 600px;
    z-index: 1;
    margin-top: 50px;
    margin-left: auto;
    margin-right: auto;
}
Modérateur
Bonjour,

Comment fais-tu pour changer le contenu de l'iframe quand un utilisateur clique sur un bouton ? Avec javascript ?

Amicalement,
Oui, j'utilise JavaScript.

function frame01() {
document.getElementById("btn_page01").style.display = "inline";
document.getElementById("frame").src = "dernierarticle.html";
document.getElementById("btn_page02").style.display = "inline";
document.getElementById("btn_page03").style.display = "inline";
document.getElementById("btn_page04").style.display = "inline";
document.getElementById("btn_page05").style.display = "inline";
}

function frame02() {
document.getElementById("btn_page01").style.display = "inline";
document.getElementById("frame").src = "carnetdebord.html";
document.getElementById("btn_page02").style.display = "inline";
document.getElementById("btn_page03").style.display = "inline";
document.getElementById("btn_page04").style.display = "inline";
document.getElementById("btn_page05").style.display = "inline";
}

function frame03() {
document.getElementById("btn_page01").style.display = "inline";
document.getElementById("frame").src = "projets.html";
document.getElementById("btn_page02").style.display = "inline";
document.getElementById("btn_page03").style.display = "inline";
document.getElementById("btn_page04").style.display = "inline";
document.getElementById("btn_page05").style.display = "inline";
}

function frame04() {
document.getElementById("btn_page01").style.display = "inline";
document.getElementById("frame").src = "sites.html";
document.getElementById("btn_page02").style.display = "inline";
document.getElementById("btn_page03").style.display = "inline";
document.getElementById("btn_page04").style.display = "inline";
document.getElementById("btn_page05").style.display = "inline";
}

function frame05() {
document.getElementById("btn_page01").style.display = "inline";
document.getElementById("frame").src = "metrouver.html";
document.getElementById("btn_page02").style.display = "inline";
document.getElementById("btn_page03").style.display = "inline";
document.getElementById("btn_page04").style.display = "inline";
document.getElementById("btn_page05").style.display = "inline";
}


Chaque "frame0x()" correspond à une page HTML appelé dans l'iframe.
Est-ce que ce serait plus représentatif si je liais un CodePen ?
Modérateur
Bonjour,

Non, pas besoin de codePen.

Remarque préliminaire : je déconseille le principe de charger le contenu des pages sous forme d'iframes incluses dans une page générique comme tu le fais. Déjà, ça force à utiliser javascript. Si c'est juste pour ça, c'est dommage. Ensuite, ça ne gagne pas vraiment de temps au changement de page. Enfin, y a des tas de problèmes pouvant survenir, dont celui que tu as concernant les doubles scrollbars. Eventuellement, ça te permet, en phase de développement, de pouvoir changer ton menu, et que les modifications soient valables pour toutes les "pages". Mais il y a aujourd'hui des éditeurs de code qui te permettent de répercuter de telles modifications sur tous les fichiers qui en ont besoin très facilement.

Dans certains cas, la solution iframe peut être envisagée. Par exemple, si tes iframes avaient toujours la même taille, ça pourrait se concevoir (cas d'iframes contenant des videos ayant toujours la même taille, etc.). Mais ici, ce n'est pas le cas.

Bon, passons aux réponses à la question.

1) Avec seulement du html et du css, on ne peut pas a priori espérer que l'iframe change de hauteur lorsque tu vas changer son contenu.

Je dis bien a priori, car il pourrait y avoir à n'importe quel moment un petit malin qui finisse par y arriver. Et s'il y en a un qui sait, qu'il le dise tout de suite ! Smiley cligne

2) Avec du javascript, on peut.

Mais ce n'est pas simple, parce que l'utilisateur a des tas de manières de changer la taille des contenus (redimensionnement de la fenêtre du navigateur, changement de la taille de police, changement d'orientation d'un mobile, etc.).

2a) Une solution relativement simple avec un setInterval est possible.

Je suis assez puriste en ce qui concerne le javacript. Et du coup, je sais bien que les setInterval sont à éviter. Mais bon, ici, ça simplifie considérablement les choses.

L'idée est à interval de temps régulier de vérifier qu'elle est la taille minimale que doit avoir l'iframe pour afficher son contenu.

La première difficulté est de calculer cette hauteur minimale. C'était compliqué par le passé. Mais ça s'est amélioré.

En 2019, on peut espérer obtenir la bonne hauteur sur la plupart des navigateurs avec la fonction suivante (où f est l'objet représentant l'iframe):

function getNewHeight(f) {
	var e;
	e = f.contentWindow.document.documentElement;
	return e.getBoundingClientRect().height;
}

Je dis bien on peut espérer car des surprises sont toujours possibles.

Il est à noter que les solutions utilisant les offsetHeight ou scrollHeight du body, ou même de son parent, ou encore un Math.max() d'une partie ou de toutes ces valeurs ne fonctionnent tout simplement pas dans le cas général.

Voici un petit code complet à adapter en utilisant la solution setInterval + modification de la hauteur de l'iframe (évidemment, on peut imaginer plein de variantes) :

EDIT: léger nettoyage du code

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0,user-scalable=yes">
<title>Iframe adaptable</title>
<style>
div.iframe-container {
    margin: 1em auto;
    padding: 1em;
    background: #ccc;
}
#frame {
	width: 100%;
	overflow: auto;
}
</style>
<script>
function changePage(url) {
	document.getElementById("frame").src=url;
}
function getNewHeight(f) {
	var e;
	e = f.contentWindow.document.documentElement;
	return e.getBoundingClientRect().height;
}
function resizeIframe() {
	var f;
	f = document.getElementById("frame");
	f.height = getNewHeight(f);
}
function magic() {
	setInterval(resizeIframe,1000);
}
</script>
</head>
<body>
<h1>Iframe adaptable</h1>
<nav>
<button onclick="changePage('page1.html')">Page1</button>
<button onclick="changePage('page2.html')">Page2</button>
</nav>
<div class="iframe-container">
<iframe onload="resizeIframe();" id="frame" scrolling="no" src="page1.html" border="0" frameBorder="no"></iframe>
</div>
<script>
window.addEventListener("load",magic,false);
</script>
</body>
</html>


2b) D'autres solutions en javascript sont possibles, mais c'est compliqué.
Il est illusoire tout seul dans son coin de faire un code qui marche en toutes circonstances. Par contre, il y a des gens qui essaient de faire ce code depuis des années et on peut éventuellement utiliser leur travail. Par exemple :
https://github.com/davidjbradshaw/iframe-resizer

Ceci étant ce sont des usines à gaz, qui sont par conséquent des nids à bug.

Bref, en résumé, soit tu abandonnes cette idée d'iframes pour la navigation, soit je te conseille la solution 2a).

Amicalement,
Modifié par parsimonhi (13 Jan 2019 - 16:38)