让访问者禁用响应式布局界面

响应式网站设计(Responsive Web Design)使用强大的媒体查询(media querie)让网站可以根据浏览者的浏览设备分辨率进行样式调整。但是,这样也产生了一个问题:有些人并不希望网站的外观在不同的浏览设备中发生改变。因为改变了之后,可能会让人产生疑问,认为自己在访问另一个网站。

虽然我不认为这会影响一大批人,但是绝大多数人肯定不懂响应式网站设计。如果有个人在电脑、平板电脑或者智能手机上访问同一个网站结果发现外观效果不同,他可能会感到很困惑。Bruce Lawson 在文章 Turning off responsive web design 中就提到了一个真实的例子。

一个同事也提到了另一个案例,响应式布局并没有很完美的客户端支持。客户经常提到布局问题等等。试想一下,如果你收到了一个邮件提到的是关于你用电脑访问看到的外观或内容,那么你用平板或者智能手机可能看不到相同的外观或者内容。当然,这种情况可能不多,但是这时候如果有一个可以切换或者关掉响应式布局的功能就好多了。

尽管这个功能不会让很多人受益,但是做这么个功能也并不是很复杂的事情。所以我在一些项目中增加了这个功能,现在想跟大家分享一下。这个方法跟 Adrian Roselli 写的 Letting Mobile Users See Desktop View of RWD Site 这篇文章中的很相似。这个功能不是很复杂,更不是什么革命性的改进,但是可以通过很多方法来实现。

如何命名响应式布局开关

有必要讨论一下怎么在网页中称呼这个功能。通常的名字是:查看桌面版布局、桌面版、完整版。而我称呼它为:查看固定宽度下的布局(当切换之后变成“查看弹性宽度下的布局”)。我并不确定这样可以帮助用户明白之间的异同,但是我认为这比起“桌面端”和“手机端”来说,描述的更加准确。有些人的浏览器窗口可能比 960px 还窄,也可能比 1200px 窄,或者是他们自己拖动设置的大小,虽然满足了媒体查询中定义的宽度,但是能在网页中显示“切换成桌面版”?

HTML 和 CSS 代码

我做了一个 Disable responsive layout 演示页面来展示效果。如果你打开了这个页面,并且调整你的浏览器窗口小于 960px ,一个就跟超链接似的开关就会显示出来,点击就可以切换。我觉得只有在媒体查询工作的时候才显示这个切换开关——如果响应式布局没有被触发,那切换个毛啊。

我选择直接把这个切换链接写进 HTML 中,而不是使用 JavaScript 临时生成。这是因为我使用后台(可以是任何后台语言,本文中使用 PHP 做演示)来处理 cookie ,这样就可以记录你是否选择了禁用响应式布局。

在前面的 demo 页面中,写入了如下的 HTML 结构,你可以自己定义:

<div id="toggle">
    <a href="?fixedwidth=1">Switch to fixed width layout</a>
</div>

使用 CSS 让其隐藏,不要写进媒体查询中:

#toggle {
    display:none;
}
.fixed #toggle {
    display:block;
}

为了方便切换,我们增加了 fixed 类。这样切换的时候,只需要对 html 对象加上 fixed 类就可以了。如果 html 对象中有这个类,就说明用户已经禁用了响应式布局,所以需要显示开关,方便他们再次启用。

下面 CSS 片段包含进媒体查询中:

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

    #toggle {
        display:block;
    }

}

上面代码实现当宽度小于 960px 的时候,触发媒体查询功能显示这个开关。如果用户已经禁用了响应式布局,上面代码将不会被加载(实现方法见下文)。

如果你的媒体查询 CSS 文件没有在一个单独的文件,要实现这个功能,可能需要做的更多工作。你可以在媒体查询的规则前面加上前缀 html:not(.fixed) 或者不使用媒体查询创建单独的文件。

JavaScript 代码

如果媒体查询的 CSS 代码被禁用,你要确保与响应式布局无关的 JavaScript 和 CSS 代码也被禁用。为了达到这个目的,你可以将下面的脚本放在单独的文件中,你也可以使用这种方法处理对应的 CSS (使用 PHP 处理),不加载这个文件。如果你没有分割成单独的文件,那么就通过检查 HTML 元素中是否有 fixed 这个类名在启用响应式布局功能脚本:

<script>
if ( !document.documentElement.className.match(/(\\s|^)fixed(\\s|$)/) ) {
    // Responsive scripts go here, likely with additional checks
    // for viewport width, media query support etc.
}
</script>

PHP 代码

在本文 Demo 中,我使用 PHP 来处理 cookie 和提供切换响应式布局的功能。你可以使用 JavaScript 来实现这样的功能,但是这样在禁用 JavaScript 的客户端无法生效。毕竟这不是很关键的功能,如果你选择使用 JavaScript 请记住如果客户端不支持 JavaScript 的时候,也要显示出一个可以看到的链接。

下面就是一个简单的 HTML 结构和必须的 PHP 代码:

<?php
    $fixedwidth = '';
    //检查是否有 $fixedwidth 这个变量,然后获取
    if ( isset($_GET['fixedwidth']) && ($_GET['fixedwidth'] != "") ) {
        $fixedwidth = $_GET['fixedwidth'];
    }
    //检查是否有对应的 cookie 内容
    if ( isset($_COOKIE['fixedwidth']) ) {
        if ( $fixedwidth == '0' ) {
            // 如果值为 0 就清除 cookie
            setcookie('fixedwidth', '', time() - 60, '/');
        } else {
            // 如果值不为零,就获取
            $fixedwidth = '1';
        }
    } else if ( $fixedwidth == '1') {
        // 浏览者想要禁用响应式布局功能,设置一个 cookie
        $expires = 60 * 60 * 24 * 60 + time(); 
        setcookie('fixedwidth', '1', $expires, '/');
    }
?>
<!DOCTYPE html>
<html lang="en" <?php if ($fixedwidth == '1') { echo 'class="fixed"'; } ?>>
<head>
    <meta charset="utf-8" />
    <title>Document title</title>
<?php
// 只在响应式布局可用的时候插入 meta[name="viewport"] 对象
if ( $fixedwidth != '1' ): ?>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
<?php endif; ?>
    <link rel="stylesheet" href="main.css" />
<?php
// 只在响应式布局可用的时候,插入 CSS 文件
if ( $fixedwidth != '1' ): ?>
    <link rel="stylesheet" href="mq.css" />
<?php endif; ?>
</head>
<body>
    <h1 ><a name="toc-5"></a>Document title</h1>
    <div id="toggle">
<?php
// Responsive is disabled, so insert a switch to flexible width
if ( $fixedwidth == '1' ): ?>
        <a href="<?php echo $_SERVER["SCRIPT_NAME"] ?>?fixedwidth=0">Switch to flexible width layout</a>
<?php
// Responsive is not disabled, so insert a switch to fixed width
else: ?>
        <a href="<?php echo $_SERVER["SCRIPT_NAME"] ?>?fixedwidth=1">Switch to fixed width layout</a>
<?php endif; ?>
    </div>
    <script>
    if ( !document.documentElement.className.match(/(\\s|^)fixed(\\s|$)/) ) {
        // Responsive scripts go here
    }
    </script>
</body>
</html>

上面的 PHP 代码肯定能进一步改进,这里只是抛砖引玉给你一个思路,你可以自己编写更符合你要求的代码。

这个功能应该在客户端中吗?

你可能会产生浏览器是否应该增加切换响应式布局功能的疑问。浏览器可能需要禁止他们自身对媒体查询的支持,而是通过网站的设置来默认显示“全尺寸”或者“桌面版”。这就是为什么我个人喜好直接开发网站,但是其他开发者却相反的先使用媒体查询功能开发“手机端”的网站,然后再开发“桌面端”布局。

如果你使用媒体查询为老的浏览器隐藏 CSS3 的功能,这也会产生问题。一个浏览器的禁用媒体查询的功能,可能会禁用所有的媒体查询中的代码,这样会产生很多布局的问题。

所以,这个功能应该交给咱们 Web 开发者来做。如果你需要这个功能,上面提供了一个不错的思路。

译者总结

禁用响应式布局确实是一个必要的功能。Bruce Lawson 在 Turning off responsive web design 这篇文章中,提到了一个小故事。说他的父亲在用手机访问一个网站的时候,发现跟电脑访问时不一样,而怀疑自己是不是在访问想访问的网站,然后关掉了。

潜行者m也曾经使用平板和智能手机做过测试,虽然智能设备上的浏览器通常可以设置“使用什么样的客户端模式(桌面、手机)来访问网站”,但是响应式布局使用的媒体查询技术,直接根据设备的参数等进行改变,不会因为客户端的代理模式(User-Agent)。特别是使用手机想要看到网站的桌面版效果,就很难实现了。

通过 JavaScript 来实现这个功能也非常简单,但是使用 PHP 更加有优势。这样可以减少不必要的 CSS 、JS 文件的引入,增强前端性能。但是 PHP 的移植性不太好。所以也可以考虑使用 JavaScript 来实现。

如果想要你的网站更加完善,如果使用了响应式布局的设计,最好加上一个禁用选项。

翻译自:Letting users disable responsive layout

热门文章