26

Is there any way to have multiple distinct HTML pages contained within a single HTML file? For example, suppose I have a website with two pages:

Page 1 : click here for page 2

and

Page 2 : click here for page 1

Can I create a single HTML file that embeds simple static HTML for both pages but only displays one at a time? My actual pages are of course more complicated with images, tables and javascript to expand table rows. I would prefer to avoid too much script code. Thanks!

paperjam
  • 8,321
  • 12
  • 53
  • 79
  • why would you want to avoid two hmtl pages? – Tim B James Nov 21 '11 at 11:37
  • I have a program that dumps thousands of small, interlinked HTML files as debug output. It would be much more convenient to have just one file output. – paperjam Nov 21 '11 at 11:40
  • 15
    "why would you want to" are non-constructive questions. Suppose I want to give someone a single "foo.html" file which appears to have multiple pages inside it, rather than a "foo.zip" which they have to unpack somewhere and then find the "index.html" in. – Kaz Jun 03 '16 at 15:10

16 Answers16

43

Well, you could, but you probably just want to have two sets of content in the same page, and switch between them. Example:

<html>
<head>
<script>
function show(shown, hidden) {
  document.getElementById(shown).style.display='block';
  document.getElementById(hidden).style.display='none';
  return false;
}
</script>
</head>
<body>
    
  <div id="Page1">
    Content of page 1
    <a href="#" onclick="return show('Page2','Page1');">Show page 2</a>
  </div>
    
  <div id="Page2" style="display:none">
    Content of page 2
    <a href="#" onclick="return show('Page1','Page2');">Show page 1</a>
  </div>
    
</body>
</html>

(Simplified HTML code, should of course have doctype, etc.)

bdkopen
  • 494
  • 1
  • 6
  • 16
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • I was wanting something like above, so I can have an english version and a french version of the web pages contained in one file ALTHOUGH if I do that how would links work to more pages and keep in the chosen language? – Poiple Shadow Aug 31 '14 at 09:51
  • @PoipleShadow: You would have to include the chosen language in the request when you go to another page. Basically that is either putting it in a cookie, or putting it in the query string of the URL. – Guffa Aug 31 '14 at 10:26
  • Thanks Guffa, I added this question which might give you a better idea of what I am after - https://stackoverflow.com/questions/25591099/multiple-pages-in-single-html-with-continuity-between-pages – Poiple Shadow Aug 31 '14 at 10:34
  • “Well, you *could*…” How????? – Kröw Jun 08 '23 at 17:56
2

I used the following trick for the same problem. The good thing is it doesn't require any javascript.

CSS:

.body {
     margin: 0em;
}

.page {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: -100vw;
    overflow-y: auto;
    z-index: 0;
    background-color: hsl(0,0%,100%);
}

  .page:target {
    left: 0vw;
    z-index: 1;
}

HTML:

<ul>
    <li>Click <a href="#one">here</a> for page 1</li>
    <li>Click <a href="#two">here</a> for page 2</li>
</ul>

<div class="page" id="one">
    Content of page 1 goes here.

    <ul>
        <li><a href="#">Back</a></li>
        <li><a href="#two">Page 2</a></li>
    </ul>
</div>

<div class="page" id="two">
    Content of page 2 goes here.

    <ul style="margin-bottom: 100vh;">
        <li><a href="#">Back</a></li>
        <li><a href="#one">Page 1</a></li>
    </ul>
</div>

See a JSFiddle.

Added advantage: as your url changes along, you can use it to link to specific pages. This is something the method won't let you do.

Hope this helps!

Binz Nakama
  • 69
  • 1
  • 4
1

JQuery Mobile has multipage feature. But I am not sure about Desktop Web Applications.

Dinesh P.R.
  • 6,936
  • 6
  • 35
  • 44
  • [AngularJS-Deeplinking](http://docs.angularjs.org/cookbook/deeplinking) supports Multipage feature (called as partials) – Dinesh P.R. Aug 08 '12 at 17:01
1

This is kind of overriding the thing of one page, but... You could use iframes in HTML.

<html>
<body>
<iframe src="page1.html" border="0"></iframe>
</body>
</html>

And page1.html would be your base page. Your still making multiple pages, but your browser just doesn't move. So lets say thats your index.html. You have tabs, you click page 2, your url wont change, but the page will. All in iframes. The only thing different, is that you can view the frame source as well.

1

Screen Rec

You could use Colker, which is built for this, but you'll have to remove the search box, and search feature code, because searching isn't compatible with the type of content you intend to use.

Page contents are stored in a java-script array, and the "page" (eg: ?page=pagename) URL parameter determines which page content to serve.

Star
  • 3,222
  • 5
  • 32
  • 48
1

Twine is an open-source tool for telling interactive, nonlinear stories. It generates a single html with multiples pages. Maybe it is not the right tool for you but it could be useful for someone else looking for something similar.

negas
  • 841
  • 12
  • 10
1

By hiding and showing one another, you can achieve this without embedding it. While Guffa's answer worked quite well, I couldn't figure out how to add more than 2 pages, and while Binz Nakama's answer fixes that, it doesn't quite let you only show Page 1 and toggle between them.

Here's the codepen I made, and here's an example I made from one of my existing websites.

HTML:

<div class="part1">
  Page 1 content goes here.
  <button onclick="hidePart1()">Go to Page 2</button>
  <button onclick="showPart3()">Go to Page 3</button>
</div>
<div class="part2">
  Page 2 content goes here.
  <button onclick="hidePart2()">Go to Page 1</button>
  <button onclick="showPart3()">Go to Page 3</button>
</div>
<div class="part3">
  Page 3 content goes here.
  <button onclick="hidePart2()">Go to Page 1</button>
  <button onclick="hidePart1()">Go to Page 2</button>
</div>

CSS:

.hide {
  display: none !important;
}

.show {
  display: block !important;
}
.part1 {
  display: block;
}

.part2 {
  display: none;
}
.part3 {
  display: none;
}

JS:

function hidePart1() {
  document.querySelector(".part1").classList.remove("show");
  document.querySelector(".part1").classList.add("hide");
  document.querySelector(".part3").classList.remove("show");
  document.querySelector(".part3").classList.add("hide");
  document.querySelector(".part2").classList.add("show");
}
function hidePart2() {
  document.querySelector(".part2").classList.remove("show");
  document.querySelector(".part2").classList.add("hide");
  document.querySelector(".part3").classList.remove("show");
  document.querySelector(".part3").classList.add("hide");
  document.querySelector(".part1").classList.add("show");
  
}
function showPart3() {
  document.querySelector(".part1").classList.remove("hide");
  document.querySelector(".part1").classList.remove("show");
  document.querySelector(".part1").classList.add("hide");
  document.querySelector(".part2").classList.remove("hide");
  document.querySelector(".part2").classList.remove("show");
  document.querySelector(".part2").classList.add("hide");
  document.querySelector(".part3").classList.remove("hide");
  document.querySelector(".part3").classList.add("show");
}

While the code above is probably not quite optimized (especially the JS), it definitely works well for me. I am still quite new to JavaScript, and not very good at it.

Edit: Added part 3 to the code. Edit: Added example.

Void
  • 11
  • 4
1

It is, in theory, possible using data: scheme URIs and frames, but that is rather a long way from practical.

You can fake it by hiding some content with JS and then revealing it when something is clicked (in the style of tabtastic).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
1

Have you considered iframes or segregating your content and using a simple show/hide?

Edit If you want to use an iframe, you can have the contents of page1 and page2 in one html file. Then you can decide what to show or hide by reading the location.search property of the iframe. So your code can be like this :

For Page 1 : iframe.src = "mypage.html?show=1"

For Page 2 : iframe.src = "mypage.html?show=2"

Now, when your iframe loads, you can use the location.search.split("=")[1], to get the value of the page number and show the contents accordingly. This is just to show that iframes can also be used but the usage is more complex than the normal show/hide using div structures.

Ashwin Krishnamurthy
  • 3,750
  • 3
  • 27
  • 49
  • user would still have to create either two html pages or write code within the html page that is loaded into the iframe to display the different content. – Tim B James Nov 21 '11 at 11:37
  • 1
    I dont think this merits a downvote because i have two options in my post. Besides, iframe is also an option to go, its only downside being the complication and the extra coding required. – Ashwin Krishnamurthy Nov 21 '11 at 11:38
1

have all the pages in distinct div areas

<div style="" id="page1">
First Page Contents
</div>

<div style="display:none" id="page2">
Second Page Contents
</div>

then use a js script to workout what you are viewing (like within an hashtag style) to navigate. Either that, or ajax to get the response from a specific file (like /pages/page1.html)

var $prehashval = "";
function loop()
{
    if (location.hash.slice(1)!=$prehashval)
        hashChanged();

    $prehashval = location.hash.slice(1);
    setTimeout("loop()", 100);
}
function hashChanged()
{
    var $output;
    switch (location.hash.slice(1))
    {
        case "page1":
            document.getElementById('page1').style.display = "";
            document.getElementById('page2').style.display = "none";
            break;
        case "page2":
            document.getElementById('page1').style.display = "none";
            document.getElementById('page2').style.display = "";
            break;
        default:
            $output = location.hash.slice(1);
    }
}
loop();
topherg
  • 4,203
  • 4
  • 37
  • 72
  • Thanks for your answer cgoddard, JS seems a little clunky - do we really need a loop? Can't a hyperlink click directly set `display="none"` on current subpage and `display=""` on the linked subpage ? – paperjam Nov 21 '11 at 11:45
  • yeah, ya could do, it would be quicker, but the loop is just designed to act as a hashchange catcher as that function its not supported by a few browser. you could do, just replace hashchanged with a function for changing page, and instead of the searching part be location.hash, just use an argument for the function. probably over complicated it a tad – topherg Nov 21 '11 at 11:53
  • This is an excellent implementation. Awesome. If we use jQuery, you could do something like: $('#page1,#page2').fadeToggle() or $('#page1 ,#page2').toggle(); to make it a little more elegant. And also you can bind a callback function if needed. – Meowtwo 117 Jul 29 '15 at 02:51
0

Solution 1

One solution for this, not requiring any JavaScript, is simply to create a single page in which the multiple pages are simply regular content that is separated by a lot of white space. They can be wrapped into div containers, and an inline style sheet can endow them with the margin:

<style>
.subpage { margin-bottom: 2048px; }
</style>
... main page ...

<div class="subpage">
<!-- first one is empty on purpose: just a place holder for margin;
     alternative is to use this for the main part of the page also! -->
</div>

<div class="subpage">
</div>

<div class="subpage">
</div>

You get the picture. Each "page" is just a section followed by a whopping amount of vertical space so that the next one doesn't show.

I'm using this trick to add "disambiguation navigation links" into a large document (more than 430 pages long in its letter-sized PDF form), which I would greatly prefer to keep as a single .html file. I emphasize that this is not a web site, but a document.

When the user clicks on a key word hyperlink in the document for which there are multiple possible topics associated with word, the user is taken a small navigation menu presenting several topic choices. This menu appears at top of what looks like a blank browser window, and so effectively looks like a page.

The only clue that the menu isn't a separate page is the state of the browser's vertical scroll bar, which is largely irrelevant in this navigation use case. If the user notices that, and starts scrolling around, the whole ruse is revealed, at which point the user will smile and appreciate not having been required to unpack a .zip file full of little pages and go hunting for the index.html.

Solution 2

It's actually possible to embed a HTML page within HTML. It can be done using the somewhat obscure data: URL in the href attribute. As a simple test, try sticking this somewhere in a HTML page:

<a href="data:text/html;charset=utf-8,<h3>FOO</h3>">blah</a>

In Firefox, I get a "blah" hyperlink, which navigates to a page showing the FOO heading. (Note that I don't have a fully formed HTML page here, just a HTML snippet; it's just a hello-world example).

The downside of this technique is that the entire target page is in the URL, which is stuffed into the browser's address input box.

If it is large, it could run into some issues, perhaps browser-specific; I don't have much experience with it.

Another disadvantage is that the entire HTML has to be properly escaped so that it can appear as the argument of the href attribute. Obviously, it cannot contain a plain double quote character anywhere.

A third disadvantage is that each such link has to replicates the data: material, since it isn't semantically a link at all, but a copy and paste embedding. It's not an attractive solution if the page-to-be-embeddded is large, and there are to be numerous links to it.

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

going along with @binz-nakama, here's an update on his jsfiddle with a very small amount of javascript. also incoporates this very good article on css navigation

update on the jsfiddle

Array.from(document.querySelectorAll("a"))
.map(x => x.addEventListener("click", 
  function(e){
    Array.from(document.querySelectorAll("a"))
    .map(x => x.classList.remove("active"));
    e.target.classList.add("active");    
  }
));
0

Let's say you have multiple pages, with id #page1 #page2 and #page3. #page1 is the ID of your start page. The first thing you want to do is to redirect to your start page each time the webpage is loading. You do this with javascript:

document.location.hash = "#page1";

Then the next thing you want to do is place some links in your document to the different pages, like for example:

<a href="#page2">Click here to get to page 2.</a>

Then, lastly, you'd want to make sure that only the active page, or target-page is visible, and all other pages stay hidden. You do this with the following declarations in the <style> element:

<style>
#page1 {display:none}
#page1:target {display:block}
#page2 {display:none}
#page2:target {display:block}
#page3 {display:none}
#page3:target {display:block}
</style>
Alpha_Pi
  • 383
  • 2
  • 13
0

An example that actually uses two separate HTML files. The example is based on this tutorial from Tutorial Republic.

app.js

$(document).ready(function(){
    $("#screen").load("page1.html")

    $(document).on("click", '#page1_button', function(event) { 
        $("#screen").load("page2.html")
    });

    $(document).on("click", '#page2_button', function(event) { 
        $("#screen").load("page1.html")
    });
});

Index.html

<!DOCTYPE html>
<html lang="eng">
<head></head>
<body>
    <div id="screen"></div>
    <!-- Import JQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <!-- Import main JS -->
    <script src="app.js"></script>
</body>
</html>

page1.html

<div>Welcome to page one</div>
<button id="page1_button" type="button">Go to page 2</button>

page2.html

<div>Welcome to page two</div>
<button id="page2_button" type="button">Go to page 1</button>

Important: Page one and page two should only have the body content, i.e., without <body> and <HTML> tags.

In case the container should span over the whole page (taken from this StackOverflow answer):

stycle.css

#screen
{
    position:fixed;
    padding:0;
    margin:0;

    top:0;
    left:0;

    width: 100%;
    height: 100%;
}
L.Lauenburg
  • 462
  • 5
  • 19
0

<html>
<head>
<script>
function show(shown, hidden) {
  document.getElementById(shown).style.display='block';
  document.getElementById(hidden).style.display='none';
  return false;
}
</script>
</head>
<body>
    <a href="#" onclick="return show('Page1','Page2');">Show page 1</a>
    <a href="#" onclick="return show('Page2','Page1');">Show page 2</a>
  <div id="Page1">
    Content of page 1
  </div>
    
  <div id="Page2" style="display:none">
    Content of page 2
  </div>
    
</body>
</html>
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 20 '22 at 14:03
0

I managed to do something like this, this is for everybody who wants 3 pages.

<html>
 <head>
<script>
function show(shown, hidden) {
  document.getElementById(shown).style.display='block';
  document.getElementById(hidden).style.display='none';
  return false;
}
</script>
</head>
<body>

   <div id="Page1">
    Content of page 1
    <a href="#" onclick="return show('Page2','Page1');">Show page 2</a>
    <a href="#" onclick="return show('Page3','Page1');">Show page 3</a>

  </div>

  <div id="Page2" style="display:none">
    Content of page 2
    <a href="#" onclick="return show('Page1','Page2');">Show page 1</a>
    <a href="#" onclick="return show('Page3','Page2',);">Show page 3</a>

  </div>

   <div id="Page3" style="display:none">
    Content of page 3
    <a href="#" onclick="return show('Page1','Page3');">Show page 1</a>
    <a href="#" onclick="return show('Page2','Page3');">Show page 2</a>

  </div> 
</body>
</html>