As pemeon said, Smarty is quite a smart (pun intended) approach for that.
If you want to learn more about the backgrounds, you might want to google for "Model-View-Controller in php" or something like that. Basically, it's about separating your view (all the presentation stuff, e.g. HTML) from your code logic (controller) and your data objects / sources (model).
Smarty is nice but you'll need a bit of learning time to figure out how the template engine is designed, how to use it and how to apply it to your specific challenges.
If you don't want such a big solution at the moment and want to start a bit smaller and easier, you could write your own very simple template "engine" around the functions file_get_contents(...) and str_ireplace. The idea looks like this: You put your HTML stuff in template-files (for example *.html or *.tpl file ending) that don't contain any php code but place holders for dynamically created content:
Example: main-layout.tpl
${Title}Here some navigation | ... | ...
${Content}
Example: welcome.tpl
Hello, ${Username}! Nice to see you!
So your username is ${Username}? Then you might want to read our terms of service before starting to use our app:
${TOS}
Example: tos-document.txt
1) An apple a day keeps the doctor away!
2) No Smoking!
3) ...
In your php script you do something like this:
$template = file_get_contents('main-layout.tpl');
if (isset($_GET['requestedpage'])) {
// Parameter given!
$requestedPage = $_GET['requestedpage'];
} else {
// No page parameter. Assume "home".
$requestedPage = "home";
}
$username = "Monty"; // get from session data
if ($requestedPage == 'home') {
// -- begin handler code for page "home" --
$title = "Start Page - Welcome";
$content = file_get_contents('welcome.tpl');
$tos = file_get_contents('tos-document.txt');
$content = str_ireplace('${TOS}', $tos, $content);
// -- end handler code for page "home" --
} else if ($requestedPage == 'aboutus') {
...
} else {
$title = "Page Not Found - Error";
$content = file_get_contents('error404.tpl');
$content = str_ireplace('${PageThatWasNotFound}', htmlentities($requestedPage), $content);
}
$output = str_ireplace('${Content}', $content, $template);
$output = str_ireplace('${Title}', htmlentities($title), $output);
$output = str_ireplace('${Username}', htmlentities($username), $output);
die($output);
?>
Using such a separation of the template and the data to insert, you can later modify your layout / template without having to touch your php scripts. For example, if you want to modify your header or footer shown on all pages, you have a single point of change as you can modularly assemble your site from several template-bricks.
To keep the php source above readable, while your source is becoming larger, you can put all the handler codes into separated php files. You'd include them by include or require into your main source file.
But watch out: You have to escape all placeholder values that might come from user inputs - regardless, if you get them from a database or directly from $_GET or $_POST (-> XSS vulnerabilities). All input is evil!