Доброго времени суток, друзья!
Сделать нечто похожее на Dashboard на Codepen.
Результат должен быть примерно следующим:

Разметка одной секции может выглядеть так:
Что здесь интересного?
Поскольку каждый блок имеет заголовок, мы может обернуть его в section (согласно спецификации section и article должны иметь заголовки).
.viewport — блок, содержащий фрейм (далее мы будет называть его просто блоком).
Атрибут src ссылается на содержимое фрейма, которое заменено «кавером» с помощью JS (об этом далее).
Seamless определяет, что содержимое фрейма должно отображаться так, словно оно является частью документа (в настоящее время не поддерживается).
Scrolling=«no» запрещает отображение полос прокрутки во фрейме.
Window.open — один из способов открыть содержимое фрейма ("_blank" — в новой вкладке).
Document.location — один из способов скачать файл.
По умолчанию размер iframe в Chrome составляет 304х154px.
Применим к section следующие стили:
Установка ширины section в 300px (+meta name=«viewport» и display: flex у родительского элемента) обеспечивает одинаковое отображение фрейма на экранах с различным разрешением.
Получается так:

А должно быть так:

Как видим, проблема заключается в том, что содержимое отображается во фрейме в натуральную величину и сам фрейм немного выходит за границы блока.
Одним из способов решения данной проблемы является масштабирование iframe:
Далее определяем размеры блока. Ширина: 1024 * 0.25 = 256px, высота: 768 * 0.25 = 192px.
При значительном количестве фреймов на странице, особенно с динамическим содержимым, мы получим очень долгую загрузку/перезагрузку и постоянные лагания при скроллинге.
Для того, чтобы решить данную проблему, мы отключаем содержимое фреймов и заменяем его картинкой. Картинка должна иметь размер 1024х768px. Если быть более точным, то мы меняем адреса файлов — значение src (на Codepen эта проблема решается с помощью короткой анимации содержимого фрейма). При наведении курсора на определенный фрейм должно отображаться его содержимое.
Решение может быть таким:
Результат можно посмотреть здесь.
Благодарю за внимание.
Задача
Сделать нечто похожее на Dashboard на Codepen.
Результат должен быть примерно следующим:

Возможное решение
Разметка одной секции может выглядеть так:
<section>
<h3>Title</h3>
<div class="viewport">
<iframe src="index.html" seamless scrolling="no"></iframe>
</div>
<div class="buttons">
<button onclick="window.open('index.html', '_blank')" title="fullscreen">demo</button>
<button onclick="document.location='code.7z'" title="download">code</button>
</div>
</section>
Что здесь интересного?
Поскольку каждый блок имеет заголовок, мы может обернуть его в section (согласно спецификации section и article должны иметь заголовки).
.viewport — блок, содержащий фрейм (далее мы будет называть его просто блоком).
Атрибут src ссылается на содержимое фрейма, которое заменено «кавером» с помощью JS (об этом далее).
Seamless определяет, что содержимое фрейма должно отображаться так, словно оно является частью документа (в настоящее время не поддерживается).
Scrolling=«no» запрещает отображение полос прокрутки во фрейме.
Window.open — один из способов открыть содержимое фрейма ("_blank" — в новой вкладке).
Document.location — один из способов скачать файл.
Весь HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width: device-width">
<title>Iframe</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<header>
<h2>Title</h2>
</header>
<main>
<section>
<h3>Title</h3>
<div class="viewport">
<iframe src="index.html" seamless scrolling="no"></iframe>
</div>
<div class="buttons">
<button onclick="window.open('index.html', '_blank')" title="fullscreen">demo</button>
<button onclick="document.location='code.7z'" title="download">code</button>
</div>
</section>
<section>
<h3>Title</h3>
<div class="viewport">
<iframe src="index.html" seamless scrolling="no"></iframe>
</div>
<div class="buttons">
<button onclick="window.open('index.html', '_blank')" title="fullscreen">demo</button>
<button onclick="document.location='code.7z'" title="download">code</button>
</div>
</section>
<section>
<h3>Title</h3>
<div class="viewport">
<iframe src="index.html" seamless scrolling="no"></iframe>
</div>
<div class="buttons">
<button onclick="window.open('index.html', '_blank')" title="fullscreen">demo</button>
<button onclick="document.location='code.7z'" title="download">code</button>
</div>
</section>
<section>
<h3>Title</h3>
<div class="viewport">
<iframe src="index.html" seamless scrolling="no"></iframe>
</div>
<div class="buttons">
<button onclick="window.open('index.html', '_blank')" title="fullscreen">demo</button>
<button onclick="document.location='code.7z'" title="download">code</button>
</div>
</section>
</main>
<footer>
<p>© All rights reserved.</p>
</footer>
</body></html>
Проблема № 1. Вписать фрейм в блок
По умолчанию размер iframe в Chrome составляет 304х154px.
Применим к section следующие стили:
section {
margin: 1em;
width: 300px;
background: rgba(0, 0, 0, 0.15);
border-radius: 5px;
box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.3);
}
Установка ширины section в 300px (+meta name=«viewport» и display: flex у родительского элемента) обеспечивает одинаковое отображение фрейма на экранах с различным разрешением.
Получается так:

А должно быть так:

Как видим, проблема заключается в том, что содержимое отображается во фрейме в натуральную величину и сам фрейм немного выходит за границы блока.
Одним из способов решения данной проблемы является масштабирование iframe:
/*
для сохранения пропорций берем одно из "популярных" разрешений экрана, например, 1024х768px,
уменьшаем масштаб фрейма до 25%,
указываем координаты точки, относительно которой будет происходить трансформация - 0 0 (верхний левый угол)
*/
iframe {
width: 1024px;
height: 768px;
transform: scale(.25);
transform-origin: 0 0;
}
Далее определяем размеры блока. Ширина: 1024 * 0.25 = 256px, высота: 768 * 0.25 = 192px.
Весь CSS
@import url("https://fonts.googleapis.com/css?family=Playfair+Display|Roboto&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
background: radial-gradient(circle, skyblue, steelblue) fixed;
display: flex;
flex-direction: column;
font-family: "Playfair Display", serif;
text-align: center;
color: #222;
}
h2 {
font-size: 2em;
text-transform: uppercase;
text-shadow: 1px 1px #ddd;
user-select: none;
}
main {
flex-grow: 1;
display: inherit;
flex-wrap: wrap;
justify-content: space-evenly;
align-content: space-evenly;
}
section {
margin: 1em;
width: 300px;
background: rgba(0, 0, 0, 0.15);
border-radius: 5px;
box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.3);
}
.viewport {
margin: auto;
width: 256px;
height: 192px;
overflow: hidden;
}
iframe {
width: 1024px;
height: 768px;
transform: scale(.25);
transform-origin: 0 0;
}
h3 {
padding: 0.5em 0;
font-size: 1em;
letter-spacing: 2px;
text-transform: uppercase;
text-align: center;
color: #ddd;
text-shadow: 1px 1px 0 #222;
user-select: none;
}
button {
border: none;
outline: none;
margin: 0.75em 0;
padding: 0.75em;
width: 100px;
background: linear-gradient(to bottom, skyblue, steelblue);
font-family: inherit;
font-weight: bold;
letter-spacing: 2px;
color: inherit;
text-transform: uppercase;
border-radius: 10px;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.4);
cursor: pointer;
transition: .2s;
}
button + button {
margin-left: 1em;
}
button:active,
button:checked,
button:focus,
button:hover {
background: radial-gradient(steelblue, skyblue);
color: #ddd;
box-shadow: inset 0 0 2px rgba(0, 0, 0, .4);
}
Проблема № 2. Отображение содержимого при наведении курсора
При значительном количестве фреймов на странице, особенно с динамическим содержимым, мы получим очень долгую загрузку/перезагрузку и постоянные лагания при скроллинге.
Для того, чтобы решить данную проблему, мы отключаем содержимое фреймов и заменяем его картинкой. Картинка должна иметь размер 1024х768px. Если быть более точным, то мы меняем адреса файлов — значение src (на Codepen эта проблема решается с помощью короткой анимации содержимого фрейма). При наведении курсора на определенный фрейм должно отображаться его содержимое.
Решение может быть таким:
// находим все фреймы в документе
let iframes = document.querySelectorAll("iframe")
// перебираем массив (на самом деле здесь мы имеем дело с объектом Nodelist, но это неважно)
for (let i = 0; i < iframes.length; i++){
let iframe = iframes[i],
// сохраняем оригинальное значение srс
originalSrc = iframe.src
// заменяем содержимое фрейма картинкой
iframe.src = "cover.jpg"
// при наведении курсора отображаем содержимое фрейма
iframe.addEventListener("mouseover", () => iframe.src = originalSrc)
// возвращаем "кавер"
iframe.addEventListener("mouseout", () => iframe.src = "cover.jpg")
}
Результат можно посмотреть здесь.
Благодарю за внимание.