html <base>标签?

我从未见过<base> HTML标签在任何地方实际使用过。它的使用是否存在意味着我应该避免使用的陷阱?

事实上,我从未注意到它在现代生产站点(或任何站点)上使用过,这让我对它持怀疑态度,尽管它似乎在简化我站点上的链接方面有有用的应用程序。


编辑

在使用base标签几个星期后,我最终发现了一些主要的陷阱,使用base标签使它比最初出现时更不可取。本质上,在base标签下对href='#topic'href=''的更改与它们的默认行为不兼容,并且这种对默认行为的更改很容易使第三方库以意想不到的方式脱离你的控制非常不可靠,因为它们在逻辑上依赖于默认行为。在处理大型代码库时,这些变化通常是微妙的,并会导致不明显的问题。从那以后,我创建了一个答案,详细说明了我在下面遇到的问题。所以,在你承诺广泛部署<base>之前,自己测试链接结果,这是我的新建议!

167033 次浏览

它可能不是很流行,因为它不是很出名。我不会害怕使用它,因为所有主流浏览器都支持它。

如果您的站点使用AJAX,您将希望确保所有页面都正确设置了AJAX,否则可能会出现无法解析的链接。

只是不要在HTML 4.01 Strict页面中使用target属性。

我从来没觉得用它有什么意义。提供很少的优势,甚至可能使一些东西更难使用。

除非您碰巧有数百或数千个链接,所有链接都指向同一子目录。这样可以节省几个字节的带宽。

事后想起来,我似乎记得IE6中的标签有一些问题。您可以将它们放置在主体的任何位置,将站点的不同部分重定向到不同的位置。这个问题在IE7中得到了修复,IE7破坏了很多网站。

它使页面更容易离线查看;您可以将完全限定的URL放在基本标记中,然后您的远程资源将正常加载。

基本标签的效果分解:

base标签似乎有一些非直观的效果,我建议在依赖<base>之前了解结果并自己测试它们!因为我发现他们试图使用基标签来处理具有不同url的本地网站,只发现有问题的影响之后,令我沮丧的是,我觉得有必要为其他人创建这些潜在陷阱的总结。

在下面的例子中,我将使用一个基标记:<base href="http://www.example.com/other-subdirectory/">,并假设代码所在的页面是http://localsite.com/original-subdirectory

主要:

没有链接、命名锚或空白引用将指向原始子目录,除非显式: base标记以不同的方式创建一切链接,包括指向base标记url的同页锚链接,例如:

    <李> < p > <a href='#top-of-page' title='Some title'>A link to the top of the page via a named anchor</a> < br > 就变成了 < br > 李<a href='http://www.example.com/other-subdirectory/#top-of-page' title='Some title'>A link to an #named-anchor on the completely different base page</a> < / p > < / > <李> < p > <a href='?update=1' title='Some title'>A link to this page</a> < br > 就变成了 < br > 李<a href='http://www.example.com/other-subdirectory/?update=1' title='Some title'>A link to the base tag's page instead</a> < / p > < / >

通过一些工作,您可以通过显式地指定这些链接链接到它们所在的页面来修复您所控制的链接上的这些问题,但是当您将依赖于标准行为的第三方库添加到组合中时,很容易造成很大的混乱。

小:

IE6需要条件注释的修复:IE6需要条件注释以避免搞砸dom层次结构,即<base href="http://www.example.com/"><!--[if lte IE 6]></base><![endif]-->,正如BalusC在上面的回答中提到的。

所以总的来说,主要的问题是使用棘手,除非你对每个链接都有完全的编辑控制,正如我最初担心的那样,这让它变得更麻烦。现在我不得不重新编写我对它的所有应用!: p

使用“片段”/散列时测试问题的相关链接:

http://www.w3.org/People/mimasa/test/base/

http://www.w3.org/People/mimasa/test/base/results


Izzy编辑:对于你们所有人和我一样对评论感到困惑:

我自己刚刚进行了测试,结果如下:

  • 不管后面有没有斜杠,对这里给出的例子都没有影响(#anchor?query只会被附加到指定的<BASE>之后)。
  • 然而,对于相对链接来说,这是不同的:省略后面的斜杠,other.htmldir/other.html将从给定示例中的DOCUMENT_ROOT开始,/other-subdirectory(正确地)被视为文件,因此被省略。

因此,对于相对链接,BASE可以很好地用于移动的页面-而锚和?queries需要显式指定文件名(BASE有一个拖尾斜杠,或者最后一个元素不对应于它所使用的文件的名称)。

把它想象成<BASE>替换文件本身的完整URL(和替换它所在的目录),你就会把事情做好。假设本例中使用的文件是other-subdirectory/test.html(在它移动到新位置之后),正确的规范应该是:

<base href="http://www.example.com/other-subdirectory/test.html”>

-等瞧,一切工作如预期:#anchor?queryother.htmlvery/other.html/completely/other.html

在决定是否使用<base>标记之前,你需要了解它是如何工作的,它可以用来做什么,它的含义是什么,并最终超过优点/缺点。


<base>标记主要简化了模板语言中相对链接的创建,因为你不需要担心每一个链接中的当前上下文。

比如说

<base href="${host}/${context}/${language}/">
...
<link rel="stylesheet" href="css/style.css" />
<script src="js/script.js"></script>
...
<a href="home">home</a>
<a href="faq">faq</a>
<a href="contact">contact</a>
...
<img src="img/logo.png" />

而不是

<link rel="stylesheet" href="/${context}/${language}/css/style.css" />
<script src="/${context}/${language}/js/script.js"></script>
...
<a href="/${context}/${language}/home">home</a>
<a href="/${context}/${language}/faq">faq</a>
<a href="/${context}/${language}/contact">contact</a>
...
<img src="/${context}/${language}/img/logo.png" />

请注意,<base href>值以斜杠结束,否则它将相对于最后一个路径进行解释。


至于浏览器兼容性,这只会导致IE的问题。<base>标记在HTML中指定为,具有结束标记</base>,因此只使用不带结束标记的<base>是合法的。然而,IE6不这么认为,整个内容<base>标签在这种情况下被放置为HTML DOM树中<base>元素的</base>0。在Javascript/jQuery/CSS中,这可能会导致第一眼无法解释的问题,即元素在特定的选择器中完全无法访问,如html>body,直到你在HTML DOM检查器中发现应该有base(和head)在两者之间。

一个常见的IE6修复是使用IE条件注释来包含结束标记:

<base href="http://example.com/en/"><!--[if lte IE 6]></base><![endif]-->

如果你不关心W3验证器,或者当你已经在HTML5上,那么你可以自我关闭它,每个web浏览器都支持它:

<base href="http://example.com/en/" />

关闭<base>标记还会立即修复WinXP SP3上IE6的精神错乱,在无限循环中使用src中的相对URI请求<script>资源。

当你在<base>标记中使用相对URI(如<base href="//example.com/somefolder/"><base href="/somefolder/">)时,另一个潜在的IE问题将显现出来。这将失败在IE6/7/8。然而,这并不完全是浏览器的错;在<base>标签中使用相对uri本身就是错误的。HTML4规范声明它应该是一个绝对URI,因此从http://https://方案开始。此函数已在HTML5规范中删除。因此,如果你使用HTML5并且只针对HTML5兼容的浏览器,那么在<base>标记中使用相对URI应该是没问题的。


至于使用命名/散列片段锚,比如<a href="#anchor">,查询字符串锚,比如<a href="?foo=bar">,路径片段锚,比如<a href=";foo=bar">,使用<base>标签,你基本上是在声明所有相对于它的链接,包括这些类型的锚。没有一个相对链接是相对于当前请求URI的(就像没有<base>标记一样)。首先,这可能会让初学者感到困惑。为了正确地构造这些锚点,你基本上需要包含URI,

<a href="${uri}#anchor">hash fragment</a>
<a href="${uri}?foo=bar">query string</a>
<a href="${uri};foo=bar">path fragment</a>

其中${uri}基本上在PHP中转换为$_SERVER['REQUEST_URI'],在JSP中转换为${pageContext.request.requestURI},在JSF中转换为#{request.requestURI}。值得注意的是,像JSF这样的MVC框架有标签,减少了所有这些样板文件,并消除了对<base>的需要。另见a.o 使用什么URL链接/导航到其他JSF页面

好吧,等一下。我认为基本标签配不上这种坏名声。

base标记的优点是它使您能够以更少的麻烦进行复杂的URL重写。

举个例子。你决定将http://example.com/product/category/thisproduct移动到http://example.com/product/thisproduct。修改.htaccess文件,将第一个URL重写为第二个URL。

有了base标签,就可以重写.htaccess了。没有问题。但是如果没有base标签,所有的相对链接都将中断。

URL重写通常是必要的,因为调整它们可以帮助您的网站的架构和搜索引擎可见性。的确,对于人们提到的“#”和“”问题,您需要变通方法。但是基本标记应该在工具包中占有一席之地。

哈希值“#”目前与基本元素一起用于跳转链接,但仅限于谷歌Chrome和Firefox的最新版本,而不是IE9。

IE9似乎会导致页面被重新加载,而不会跳转到任何地方。如果你在一个iframe的外部使用跳转链接,同时引导该框架在该框架内的另一个页面上加载跳转链接,你将得到加载在该框架内的跳转链接页面的第二个副本。

Drupal最初依赖于<base>标签,后来由于HTTP爬虫程序的问题而决定不使用。缓存。

我一般不喜欢发布链接。但是这个确实值得分享,因为它可以让那些寻找<base>标签的真实世界体验细节的人受益:

http://drupal.org/node/13148

有一件事要记住:

如果你要开发一个在iOS上的UIWebView中显示的网页,那么你必须使用BASE标签。否则它根本不会起作用。无论是JavaScript, CSS,图像-没有一个将工作在UIWebView下的相对链接,除非标签BASE被指定。

我以前也遇到过这种情况,直到我发现。

还有一个站点使用了base - tag,出现了描述的问题。(升级jquery后),能够修复它有TAB url像这样:

<li><a href="{$smarty.server.REQUEST_URI}#tab_1"></li>

这使得他们“本地化”

我使用的参考资料:

http://bugs.jqueryui.com/ticket/7822 http://htmlhelp.com/reference/html40/head/base.html http://tjvantoll.com/2013/02/17/using-jquery-ui-tabs-with-the-base-tag/ < / p >

要决定是否应该使用它,您应该了解它的功能以及是否需要它。这已经在这个答案中部分概述了,我也贡献了它。但是为了更容易理解和理解,这里有第二个解释。首先我们需要了解:

没有使用<BASE>,浏览器如何处理链接?

对于一些例子,让我们假设我们有这些url:

A) http://www.example.com/index.html
B) http://www.example.com/
C) http://www.example.com/page.html
D) http://www.example.com/subdir/page.html < / p >

A和B都会将相同的文件(index.html)发送到浏览器,C当然发送page.html, D发送/subdir/page.html

让我们进一步假设,两个页面都包含以下类型的链接:

  1. 完全限定的绝对链接(http://www...)
  2. 本地绝对链接(/some/dir/page.html)
  3. 相对链接,包括文件名(dir/page.html),和
  4. 与“分段”相关的链接;only (#anchor?foo=bar)。

浏览器接收页面,并呈现HTML。如果它找到某个URL,它需要知道指向哪里。对于Link 1)来说,这一点总是很清楚的,因为它是按原样进行的。所有其他依赖于呈现页面的URL:

URL     | Type | Result
--------+------+--------------------------
A,B,C,D |    2 | http://www.example.com/some/dir/page.html
A,B,C   |    3 | http://www.example.com/dir/page.html
D       |    3 | http://www.example.com/subdir/dir/page.html
A       |    4 | http://www.example.com/index.html#anchor
B       |    4 | http://www.example.com/#anchor
C       |    4 | http://www.example.com/page.html#anchor
D       |    4 | http://www.example.com/subdir/page.html#anchor

现在是什么改变了 <BASE>被使用?

<BASE>应该替换URL 就像浏览器显示的那样。因此,它呈现所有链接,就像用户调用了<BASE>中指定的URL一样。这解释了其他几个答案中的一些困惑:

  • 同样,“完全合格的绝对链接”;没有任何变化("type 1")
  • 对于“本地绝对链接”;,目标服务器可能会改变(如果在<BASE>中指定的值与用户最初调用的值不同)
  • “相对URLs"在这里变得很重要,所以你必须特别注意如何设置<BASE>:
    • 最好避免将其设置为目录
      这样做,“类型3”的链接;(相对dir +文件名)可能继续工作,但它肯定会破坏那些&;type 4&;(相对+段);除了&;case "(没有路径或文件名).
    • 在大多数情况下,将其设置为完全限定文件名会产生所需的结果。

举个例子最好地说明了这一点

说你想“美化”;一些URL使用mod_rewrite:

  • 文件:<DOCUMENT_ROOT>/some/dir/file.php?lang=en
  • real URL: http://www.example.com/some/dir/file.php?lang=en
  • 用户友好的URL: http://www.example.com/en/file

让我们假设mod_rewrite被用来透明的将用户友好的URL重写为真实的URL(没有外部重定向,因此“;用户友好的”;一个停留在浏览器的地址栏,而真正的一个被加载)。现在该怎么办?

  • no <BASE>指定:中断所有相对链接(因为它们现在基于http://www.example.com/en/file)
  • <BASE HREF='http://www.example.com/some/dir>:完全错误。dir将被认为是指定URL的文件部分,因此,所有相对链接仍然是断开的。
  • <BASE HREF='http://www.example.com/some/dir/>:已经好多了。但是“类型4”的相对链接;还是坏了(除了&;case ")。
  • <BASE HREF='http://www.example.com/some/dir/file.php>:没错。所有东西都可以用这个。

最后一点

请记住,这适用于文档中的所有 url:

  • <A HREF=
  • <IMG SRC=
  • <SCRIPT SRC=
  • ...

我找到了一种方法来使用<base>和基于锚的链接。你可以使用JavaScript来保持像#contact这样的链接正常工作。我在一些视差页面中使用了它,它很适合我。

<base href="http://www.mywebsite.com/templates/"><!--[if lte IE 6]></base><![endif]-->


...content...


<script>
var link='',pathname = window.location.href;
$('a').each(function(){
link = $(this).attr('href');
if(link[0]=="#"){
$(this).attr('href', pathname + link);
}
});
</script>

你应该用在这一页的末尾

在页面内联SVG图像的情况下,当使用base标记时,会出现另一个重要的问题:

因为使用base标记(如上所述),你有效地失去了使用相对哈希url的能力,如in

<a href="#foo">

,因为它们将根据基本URL而不是当前文档的位置进行解析,因此不再是相对的。 因此,您必须将当前文档的路径添加到这些类型的链接中,如

<a href="/path/to/this/page/name.html#foo">

因此,base标记的一个看似积极的方面(它将长URL前缀从锚标记中移开,并获得更好、更短的锚)完全适得其反。

在你的页面中内联SVG时,这尤其令人讨厌,无论是静态SVG还是动态生成的SVG,因为在SVG可以有很多这样的引用中,它们都会在使用base标记时立即中断,在大多数,但不是所有的用户代理实现上(Chrome至少在撰写本文时仍然可以在这些场景中工作)。

如果你正在使用模板系统或其他工具链来处理/生成页面,我总是会尝试摆脱base标记,因为在我看来,它带来的问题比它解决的问题要多。

在AngularJS中,BASE标签默默地破坏了$cookieStore,我花了一段时间才弄清楚为什么我的应用程序不能再编写cookie了。警告……

另外,你应该记住,如果你在非标准端口上运行你的web服务器,你也需要在base href上包含端口号:

<base href="//localhost:1234" />  // from base url
<base href="../" />  // for one step above

Base href示例

举一个典型的带有链接的页面:

<a href=home>home</a> <a href=faq>faq</a> <a href=etc>etc</a>

. .链接到一个diff文件夹:

..<a href=../p2/home>Portal2home</a> <a href=../p2/faq>p2faq</a> <a href=../p2/etc>p2etc</a>..

使用基地href,我们可以避免对基本文件夹进行__abc1:

<base href=../p2/>
<a href=home>Portal2-Home</a> <a href=faq>P2FAQ</a> <a href=contact>P2Contact</a>

所以这是一种胜利。然而,页面经常包含不同的url,目前的web支持每页只有一个base href,所以win很快就会丢失,因为base不是base∙hrefed重复,例如:

<a href=../p1/home>home</a> <a href=../p1/faq>faq</a> <a href=../p1/etc>etc</a>
<!--.. <../p1/> basepath is repeated -->


<base href=../p2>
<a href=home>Portal2-Home</a> <a href=faq>P2FAQ</a> <a href=contact>P2Contact</a>
人力资源> < p > < 结论< / >强

(基本目标可能有用)Base href是无用的 as:

  • page等于湿,因为:
    • 默认基础文件夹[–父文件夹]⇌完美的(除非不必要的/罕见的异常)𝒞 2)。
    • 当前web ⇌不支持多个基本引用
    • 李< / ul > < / >

    相关的

我的建议是不要在管理url路径时使用<base>元素。为什么?

这只是把一个问题换为另一个问题。如果没有基本元素,您可以为相对路径和链接使用任何您喜欢的路径系统,而不必担心它们会中断。当你将基本元素设置为一个路径时,你就被“锁定”到设计所有url的工作路径,现在必须从基本路径更改所有路径。坏主意!

这意味着您现在必须编写更长的路径,并跟踪每条路径相对于这个基底的位置。更糟糕的是……当使用<base>元素时,他们建议你使用完全限定的基本路径来支持旧的浏览器(“https://www.example.com/”),所以现在你已经硬编码了你的域名到你的页面中,或者让你的所有链接依赖于一个有效的域名路径。

另一方面,当你再次从你的网站中删除基本路径时,你现在可以再次自由地使用更短的相对路径,这可以是完全限定的,从根目录使用绝对路径,或者使用真正相对于你所在的文件和文件夹的路径。它更灵活。最好的是,像“#hello”这样的片段可以正常工作,不需要任何额外的修复。再说一次,人们在制造不存在的问题。

另外,上面提到的使用基本url来帮助您将网页文件夹迁移到新的子文件夹位置的论点在今天并不重要,因为大多数现代服务器允许您快速将任何子文件夹设置为任何域下的新应用程序根文件夹。web应用程序的定义或“根”现在不受文件夹或域的限制。

这场争论看起来有点傻。因此,我建议去掉base url,并支持不使用它的旧的本地服务器-客户机默认路径系统。

注意:如果你的问题是控制路径由于一些新的API系统,解决方案很简单…在API中所有url和链接的路径上保持一致。不要依赖于浏览器对base或HTML5的支持,也不要像javascript API小孩子那样依赖于更新的马戏团把戏。简单地路径所有的锚标签一致,你将永远不会有问题。更重要的是,不管使用什么路径系统,您的web应用程序都可以立即移植到新的服务器上。

旧的又变新了!基本元素显然是试图为20年前的Web世界中从未存在过的问题创建解决方案,更不用说今天了。

我将在从来没有设置<base href>标记的原因列表中再添加一个参数。正如许多人在这里注意到的那样,设置<base href>会改变#anchor和?query URL的行为——它们会附加到基本的href,而不是文档自己的URL的回退基础。

你可能认为设置<base href="https://example.com/the/documents/own/url">可以解决这个问题,并且一切都将正常运行。你错了。

在现实世界的web中,?query=参数一直用于会话属性(如谷歌Analytics)和许多其他事情。这些参数中有许多是专门供脚本在客户端使用的;服务器不会关心它们,也不会对它们做任何事情。

假设你正在提供example.com/landing-page,带有<base href="example.com/landing-page">,以及页面上指向#menu的链接。然后有人通过URL example.com/landing-page?source=my-marketing-campaign到达那里。

如果没有<base href>,当他们单击#菜单时,浏览器将识别页面内导航并立即跳转到该部分。

但是,由于您定义的base href example.com/landing-page缺少查询参数source=my-marketing-campaign,浏览器不能确定认为它是一个页内链接。因此,单击#menu将触发一个 HTTP请求,页面(及其所有非缓存资产)将重新加载。最好的情况是,这是对各方时间和带宽的毫无意义的浪费。在最坏的情况下,状态和数据可能会丢失。

对于静态站点来说,这是没有办法的。如果你正在使用CMS,你可能会想一下,你可以动态地将<base href>设置为请求URL,包括所有参数。虽然这可以解决刷新问题,但你最终会遇到缓存问题和一个噩梦般的安全漏洞

底线:<base href>会给你带来麻烦,不管你把它设置成什么。不要这样做。

如果你担心恶意脚本可能注入自己的<base href="evil.com">标记(例如在立即重定向攻击中),2022年的最佳解决方案似乎是将基本uri指令添加到你的内容安全策略中。