在 DOM 中移动元素以实现响应式 Web 设计

Posted

技术标签:

【中文标题】在 DOM 中移动元素以实现响应式 Web 设计【英文标题】:Moving Elements in DOM for Responsive Web Design 【发布时间】:2014-06-07 22:54:00 【问题描述】:

简要说明

我创建了一个响应式网站,它实际上具有三个视图(桌面、平板电脑、移动)。大多数设计都是通过 CSS 使用媒体查询来改变的(对于响应式网站来说应该是这样)。然而,部分设计过于复杂,无法简单地通过 CSS 进行操作,因为 html 实际上需要在 DOM 中移动。我知道这听起来不太好,但我看不出在不移动 HTML 中的某些元素的情况下如何复制这种设计。

因此,考虑到上述情况,我现在计划编写一个函数,为每个不同的“响应式视图”创建自定义事件。当每个事件被触发时(与 CSS 媒体查询同步),它将执行一些 javascript 来移动/动画任何使用 CSS 无法充分操作的元素。

我的问题

这是最好的方法吗?如果不是,我还有什么其他选择?有没有我可以查看和学习的现有库?

我的实际问题是;对于响应式网页设计,在 DOM 中移动元素的最佳方法是什么?

进一步说明

如果以上内容不清楚,请阅读以下内容:

考虑这三种不同的观点:

现在考虑前两个视图的代码:

桌面

<div id="some_container">
    <nav>
        <ul>
        </ul>
    <nav>
    <p>Some Text</p>
    <!-- The rest of the content -->
</div>

平板电脑

<div id="some_container">
    <p>Some Text</p>
    <nav>
        <ul>
        </ul>
    <nav>
    <!-- The rest of the content -->
</div>

注意nav 标签已移至p 标签下方...

【问题讨论】:

我只需添加两次导航或文本,然后根据媒体查询仅显示您想要的。 @Cerbrus 会增加加载时间.....理想情况下不是好主意... @C-link 非常非常非常少。 @C-link:加载时间的差异非常微不足道。它类似于具有额外一段文本的页面。 也许需要额外加载 2kB。 @C-link:我无法理解您的问题。 “在不同的地方多次放置”? 【参考方案1】:

有很多方法比如appendTo

//check for the window width
if($(window).width() < 700)
  //append to the p  
  $('#some_container nav').appendTo('#some_container p');

【讨论】:

感谢您的回答,但我知道如何根据窗口大小附加 DOM 和移动元素,我想知道它是否是实现此同步的最佳方法使用 CSS 媒体查询? 使用 css 媒体查询你不能移动元素,因为@Cerbus 说你必须这样做...... 如果您的意思是使用 js 进行媒体查询,那很好。只需搜索一下,您就会发现很多结果......【参考方案2】:

我建议您使用.insertAfter().resize()/.ready() 根据页面大小移动元素:

$(window).resize()
    resize();


$(document).ready()
    resize();


function resize()
    if($(window).width() < 480)
    
        //Mobile
        $("#some_container nav").insertAfter("#some_container p");
    
    else if($(window).width() < 800)
    
        //Tablet
        $("#some_container nav").insertAfter("#some_container p");
    
    else
    
        //Desktop
        //Leave original layout
    

【讨论】:

这是我打算写的函数的一个非常基础的版本。当我想从桌面->移动(跳过平板电脑)等时出现问题...... 你有什么问题? 说实话,没有问题,我可以很轻松地写出这段代码。我只是想确定这是实现我所解释的最佳方法。 最佳是主观的。我只能为您提供一个好的、可行的解决方案。 解决方案需要考虑所有情况,但那又如何呢?这同样适用于 CSS 解决方案。他必须明确地将副本准确地放在源中他想要的位置。从表面上看,案件的数量是有限的,所以“如果他有超过 9000 个不同的案件呢?”无关紧要。那太荒谬了。【参考方案3】:

你可以试试这个:

假设这个 HTML:

<div id="some_container">
    <nav id="n1">
        <ul>
            <li>1</li>
            <li>2</li>
        </ul>
    </nav>
    <p>Some Text</p>
    <nav id="n2">
        <ul>
            <li>1</li>
            <li>2</li>
        </ul>
    </nav>
</div>

您只需要以下 css:

#n1
    display:none;


@media only screen 
and (min-width : 600px) 
    #n1
        display:block;
    
    #n2
        display:none;
    

Fiddle example

这基本上会根据屏幕大小切换您看到的两个导航部分中的哪一个。它的缺点是你的源中有重复的html(数据量的差异真的可以忽略不计),但你不需要JavaScript来获得效果,并且禁用JS的设备只会显示一个ul

这种方式的好处在于它非常具有可扩展性。在不同的页面上需要这种“效果”吗?您只需要编辑 [u]that[/u] 页面。不要乱用 JavaScript,硬编码新的类/案例。

【讨论】:

我确实考虑过这种方法,但我只是不喜欢重复 HTML 的想法...... @BenCarey:导航栏有多少个字符?我绝对确定性能差异可以忽略不计。 这是非常真实和公平的,但这只是一个例子。该网站有几个元素需要移动,我只是不太相信这是最好的方法......更不用说它使代码更难维护,尽管它很少,维护 老实说,我最初没有使用这种方法的原因是因为我不想重复代码,我觉得这不是最有效的解决方案。但是,现在进一步研究了它,我觉得它可能是更好的解决方案。仅仅因为它按预期加载页面,它不需要等待 jQuery 加载来移动元素,我可以在 CSS 中处理动画,它不会影响加载时间,也不会使代码更加更难维护。最后,我得到了一个 13k 代表的建议,所以我倾向于相信你说的话:-) 但重复的内容对 SEO 非常不利【参考方案4】:

我刚刚编写了一个 jQuery 插件,它正是这样做的,看看here。基本上,它会根据行和列自动构建一系列布局,然后将其用于上面显示的不同视图

【讨论】:

【参考方案5】:

enquire.js 库允许您触发 JS 函数以响应 CSS 媒体查询,从而解决了这个问题。因此,您可以根据不同的屏幕尺寸运行 detach() 和 append() 逻辑。它是轻量级的启动。

见:http://wicky.nillia.ms/enquire.js/

【讨论】:

看起来它可能不再更新了【参考方案6】:

创建重复内容来解决响应式设计挑战并不是最佳做法。它使标记更难维护(特别是当另一个开发人员接管项目并且没有意识到它必须在多个位置更新时),它会增加文件大小(如果文件大小不重要,我们不会缩小我们的 CSS/JS 或 GZIP 我们的 HTML),辅助技术和其他不考虑 CSS 的 Web 代理将其视为重复内容。

这很混乱,我看不出有人会认为这是最佳实践。

虽然 JavaScript 也不理想,但我认为将其用作渐进增强的一种形式没有问题。我最近发现自己经常使用它,所以我为它创建了一个 jQuery 插件:https://github.com/thomashigginbotham/responsive-dom

示例用法:

var $mainNav = $('.main-nav');

$mainNav.responsiveDom(
    appendTo: '.sidebar',
    mediaQuery: '(min-width: 600px)'
);

【讨论】:

【参考方案7】:

这可能会带来一系列全新的问题,但是您能否在要移动的元素上使用 position: absolute,并让它们根据屏幕大小在页面周围重新定位?

【讨论】:

【参考方案8】:

我现在正在用导航做这件事,我需要移动到桌面的标题和移动设备上的汉堡菜单标题下方。我在正在调整大小的窗口上有一个事件侦听器,它调用一个检查屏幕大小并将其传递给我的 toggleNavigation 函数的函数。我有这个单独的,因为除了在 checkBreakPoint 中调用的函数之外,我还有一些其他函数没有列出。然后为了确保它不会不断地移动我的 dom 或重新附加它,我首先检查它在哪个父容器中,并且只有在它不在我期望的那个屏幕尺寸的容器中时才移动它。我的项目要求它没有任何外部依赖项,所以这只是用纯 Javascript 完成,然后我使用媒体查询根据屏幕大小设置元素样式。

var mainNav = document.getElementById('rww_main_nav'); //element I want to move
var tieredHeader = document.getElementById('rww_tiered_header'); //where it should be on mobile
var branding = document.getElementById('rww_branding'); //where it should be on desktop

window.addEventListener("resize", checkBreakPoint);

function checkBreakPoint() 
        //width of viewport
        var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
        toggleNavLocation(w);


function toggleNavLocation(screensize) 
    if (screensize > 999) 
        if (mainNav.parentElement.id === 'rww_tiered_header') 
            branding.appendChild(mainNav);
        
     else 
        if (mainNav.parentElement.id === 'rww_branding') 
            tieredHeader.appendChild(mainNav);
        
    

【讨论】:

【参考方案9】:

如果您不想制作 javascript,请使用网格技术。

<div class="main_container">
    <nav class="grid_nav">
        <ul>
        </ul>
    <nav>
    <div class="grid_text">
        <p>Some Text</p>
    </div>
    <!-- The rest of the content -->
</div>

.main_container
  display: grid;
  @media screen and (max-width: 500px)  //mobile
    grid-template-rows:    1fr 1fr;
    grid-template-areas: "gridnav"
                         "gridtext";
  
  @media screen and (min-width: 500px) //web
    grid-template-rows:    1fr 1fr;
    grid-template-areas: "gridtext"
                         "gridnav";
  


.grid_nav
  grid-area: gridnav;

.grid_text
  grid-area: gridtext;

但仅当运动在“main_container”内时

问候...

【讨论】:

【参考方案10】:

如今,要更改设计中特定元素的位置,您无需在 DOM 中移动它们,只需使用 CSS order 属性更改它们的显示顺序:

所以给出以下 HTML 结构:

<div id="container">
    <nav>
        <ul>
          <li>Item 1</li>
          <li>Item 2</li>
        </ul>
    </nav>
    <p>Some text</p>
    <!-- The rest of the content -->
</div>

只要您的容器是 flex 元素,您就可以通过给其中一个或多个子元素一个 order 属性来操纵其子元素的显示顺序(如果您愿意,可以在媒体查询中)。这有一个从零开始的值,所以 '1' 将把它排在第二位:

#container

  display: flex;
  flex-direction: column;


@media (max-width: 400px)

  nav
  
    order: 1;
  

在小于 401 像素的屏幕上,您会看到:

一些文字

项目 1 第 2 项

【讨论】:

以上是关于在 DOM 中移动元素以实现响应式 Web 设计的主要内容,如果未能解决你的问题,请参考以下文章

用Adobe XD 12更智能的快速完成响应式设计

提升移动设备响应式设计的8个建议

移动WEB开发之响应式布局

移动WEB开发之响应式布局

微交互:提升移动设备响应式设计的8个建议

前端库Bootstrap框架:「01] 使用 Fluid 容器实现响应式设计