Onepage or Singlepage design sites are quite popular these days especially for sites that don't provide too much content, landing pages or microsites and the like. Creating those in TYPO3 is easy enough with FluidTYPO3. Here's how.

All sections of the page will be added as subpages so basically we'll need two page layouts/templates: one that holds the onepage design itself and one that holds a single section of the page. Let's name them Onepage.html and OnepageSection.html. The latter is ridiculously simple.

myext/Resources/Private/Templates/Page/OnepageSection.html

<div xmlns="http://www.w3.org/1999/xhtml" lang="en"
      xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
      xmlns:flux="http://typo3.org/ns/FluidTYPO3/Flux/ViewHelpers"
      xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers">

    <f:layout name="OnepageSection"/>

    <f:section name="Configuration">
        <flux:form id="onepagesection">
            <flux:grid>
                <flux:grid.row>
                    <flux:grid.column colPos="0" name="content"/>
                </flux:grid.row>
            </flux:grid>
        </flux:form>
    </f:section>

    <f:section name="Content">
        <v:content.render column="0"/>
    </f:section>

</div>

myext/Resources/Private/Layouts/OnepageSection.html

<f:layout name="OnepageSection"/>
<f:render section="Content" />

Now, to render all subpages as sections inside the parent page we'll abuse <v:page.menu /> to fetch them:

<v:page.menu levels="1" as="sections">
...
</v:page.menu>

Next step is to iterate over all subpage records provided by the menu viewhelper and render the content elements of those subpages in a <section /> tag. Again vhs is our friend with <v:content.render />:

<v:page.menu levels="1" as="sections">
    <f:for each="{sections}" as="section">
        <section id="section-{section.uid}">
            <v:content.render pageUid="{section.uid}" />
        </section>
    </f:for>
</v:page.menu>

Last but not least we need a menu that points to each single section. <v:page.menu /> one more time:

<v:page.menu levels="1" as="sections">
    <nav>
        <ul class="menu">
            <f:for each="{sections}" as="section" iteration="iteration">
                <li><a href="#section-{section.uid}" title="{section.title}">{section.title}</a></li>
            </f:for>
        </ul>
    </nav>
</v:page.menu>

Of course you'll have to include some JavaScript to add the scrolling functionality which is not covered here.

The complete page template now looks like this:

myext/Resources/Private/Templates/Page/Onepage.html

<div xmlns="http://www.w3.org/1999/xhtml" lang="en"
      xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
      xmlns:flux="http://typo3.org/ns/FluidTYPO3/Flux/ViewHelpers"
      xmlns:v="http://typo3.org/ns/FluidTYPO3/Vhs/ViewHelpers">

    <f:layout name="Onepage"/>

    <f:section name="Configuration">
        <flux:form id="onepage"/>
    </f:section>

    <f:section name="Navigation">
        <v:page.menu levels="1" as="sections">
            <nav>
                <ul class="menu">
                    <f:for each="{sections}" as="section" iteration="iteration">
                        <li><a href="#section-{section.uid}" title={section.title}">{section.title}</a></li>
                    </f:for>
                </ul>
            </nav>
        </v:page.menu>
    </f:section>

    <f:section name="Content">
        <v:page.menu levels="1" as="sections">
            <f:for each="{sections}" as="section" iteration="iteration">
                <section id="section-{section.uid}">
                    <v:content.render pageUid="{section.uid}" />
                </section>
            </f:for>
        </v:page.menu>
    </f:section>

</div>

Notice the empty Flux configuration section (which is required to create a template) that doesn't contain a grid as we don't add content to the page directly. You can add some configuration options of course depending on your requirements.

And a minimalistic layout:

myext/Resources/Private/Layouts/Onepage.html

<div class="onepage">
    <div class="navigation">
        <f:render section="Navigation" />
    </div>
    <div class="sections">
        <f:render section="Content" />
    </div>
</div>

As already mentioned we can now add a page to the pagetree that will hold the onepage design. For this page we select Onepage as Page Layout - this page and OnepageSection as Page Layout - subpages. All subpages added to this page will now be rendered as individual sections.

That's it.

Update:

To make the page sections configurable we can add a flux form to OnepageSection template and access its values with the <flux:form.data /> viewhelper. In the following example I added a textfield cssClasses:

myext/Resources/Private/Templates/Page/Onepage.html

    <f:section name="Content">
        <v:page.menu levels="1" as="sections" showHiddenInMenu="true">
            <f:for each="{sections}" as="section" iteration="iteration">
                {section -> flux:form.data(table: 'pages', field: 'tx_fed_page_flexform') -> v:variable.set(name: 'sectionFormData')}
                <section id="{section.nav_title -> v:format.url.sanitizeString()}" class="{sectionFormData.cssClass}{f:if(condition: '{iteration.isFirst}', then: ' first')}{f:if(condition: '{iteration.isLast}', then: ' last')}">
                    <div class="container">
                        <v:content.render pageUid="{section.uid}" />
                    </div>
                </section>
            </f:for>
        </v:page.menu>
    </f:section>
comments powered by Disqus