首页 > 解决方案 > 可调整大小的响应式切换 iframe

问题描述

我需要一个带有 2 个 IFRAME 的布局,可以通过 javascript 在屏幕上切换而不刷新内容(它们只是改变位置),并且可以调整列的大小。在移动设备上,它们应该 100% 宽度堆叠。

此处绘制示例

https://codepen.io/az3l10/pen/vYgVmeP

function toggleLayout() {
  document.querySelector('main').classList.toggle('social');
 
}
main div {
  position: absolute;
  width: calc(100% - 400px);
  height: 100%
  top: 0; 
  left: 0;
}

[orange] {
  position:absolute;
  right:0px;
  background-color: #FFAD77;
}

[yellow] {
    position: absolute;
  background-color: #FFE377;
  width:400px;
  height:30px;
  left:calc(100% - 400px);
}


[green] {
    position: absolute;
  background-color: lightgreen;
  width:400px;
  height:300px;
  left:calc(100% - 400px);
  top:30px;
}


[purple] {
  position: absolute;
  width:400px;
  height:calc(100% - 330px);

  left:calc(100% - 400px);
  top:330px;
  background-color: #FF77C8;
  
}

main.social div {
 
}



main.social [orange] {
 left:calc(100% - 400px);
 top:30px;
  width:400px;
  height:1000px;

  background-color: #FFE377;
  
  
}


main.social [green] {
 position: absolute;
 top:0;
 left:0;
 width: calc(100% - 400px);
 height: calc(100%);
 
  background-color: lightgreen;
}


@media only screen and (max-width: 1580px) {

[orange] {
  position:relative;
  left:0px;
  top:0px;
  width:100%;
  background-color: #FFAD77;
}

[yellow] {
  position:relative;
  left:0px;
  top:0px;
  width:100%;
  background-color: #FFE377;
}

[purple] {
  position:relative;
  left:0px;
  top:0px;
  width:100%;
  height:600px;
    background-color: #FF77C8;
  }

[green] {
  position:relative;
  left:0px;
  top:0px;
  width:100%;
  height:10px;
  background-color: lightgreen;
   
}


main.social.sociald {
  height:600px;
}


main.social.chatd {
  height:10px;
}

}
<main>
 <div orange> 
ORANGE
  </div>

    <div yellow>

        <button onclick="toggleLayout">TOGGLE</button>

        
    </div>

    <div green id="sociald">    
    <figure style="width:100%;height:100%;margin:0px">
        <iframe id="framesoc" border=0 style="width:100%;height:100%" src="https://www.google.com"></iframe>
        </figure>
    
    </div>

    <div purple id="chatd"> 
        
        <figure style="width:100%;height:100%;margin:0px">
        <iframe id="framechat" border=0 style="width:100%;height:100%" src="https://www.calm.com/breathe"></iframe>
        </figure>
        
    </div>

</main>

 
</body>
</html>

我遇到的问题是,由于 DIV 位置是绝对的,我无法调整列的大小,并且如果我更改定位,我无法切换。

有人可以帮忙吗?

标签: javascripthtmljquerycssdom

解决方案


如果可以使用CSS FlexboxCSS Grid实现,请不要使用绝对定位。

移动优先

我们知道我们想要两个元素 A 和 B 出现在我们的网站上,并且这两个元素属于一起。这意味着,我们创建了两个包含在分组元素中的元素:

/* Ignore; for demonstration-purposes */
html {height:100%}
body {margin:0;min-height:100%}
#a, #b {min-width:100px;min-height:100px}
#a {background-color:red}
#b {background-color:blue}
<div class="wrapper">
  <div id="a"></div>
  <div id="b"></div>
</div>

有了(本质上)display: block设置了这两个,默认的 CSS 就足够了,所以不需要写任何东西。

现在,当在更大的屏幕上查看该网站时,我们希望有...:

  • ... 2×2 网格
  • ...网格右上角的切换按钮(简单地说:单个复选框),用于交换 A 和 B 的位置
  • ...占据整个第一列的第一个(“选定”)元素

我们修改 HTML 以适应我们想要的结果,然后开始编写 CSS。
我们基本上禁用了仅限大屏幕的元素,并(重新)在规则中启用它们和其他想要的样式@media。此外,我们添加网格,并默认提供#a-class selected

现在,要添加交换功能,我们需要一些 JavaScript。
我们希望将selected-class 添加到 A 或 B,具体取决于 checkboxes checked-property。

总而言之,代码现在看起来像这样:

const a = document.querySelector('#a');
const b = document.querySelector('#b');
document.querySelector('input').addEventListener('click', evt => {
  if (evt.target.checked) {
    b.classList.add('selected');
    a.classList.remove('selected');
  } else {
    a.classList.add('selected');
    b.classList.remove('selected');
  }
});

/* Alternatively (same effect)
const wrapperElements = document.querySelectorAll('.wrapper>*:not(label)');
document.querySelector('input').addEventListener('click', evt => {
  let i = Number(!!evt.target.checked);
  wrapperElements[i].classList.add('selected');
  wrapperElements[++i % 2].classList.remove('selected');
});
*/
/* Ignore; for demonstration-purposes */
html {height:100%}
body {margin:0;min-height:100%}
#a, #b {min-width:100px;min-height:100px}
#a {background-color:red}
#b {background-color:blue}

/* The CSS */
label {display: none}

@media only screen and (min-width: 768px) { /* When at least 768px, then: */
  .wrapper {
    display: grid;
    grid-template-rows: auto 1fr;
    grid-template-columns: 1fr auto;
  }
  label {
    display: initial;
    grid-area: 1 / 2 / 2 / 3;
  }
  .selected {grid-area: 1 / 1 / -1 / 1}
}
<div class="wrapper">
  <label><input type="checkbox">Toggle A/B</label>
  
  <div id="a" class="selected"></div>
  <div id="b"></div>
</div>


推荐阅读