Adding Style

Use style attribute to add style to a view. The style attribute is defined using a TypedDict object which means it's a type constrained dictionary. What this means is, you can utilise the autocomplete from your IDE for writing code faster. And since it's type constriained you can also utilise a tool like mypy to make sure you are not defining any wrong attributes. Autocomplete

"""Simple hello example."""

from ph7.html import body, div, html

template = html(
    body(
        div(
            "Hello, World!",
            style={
                "height": "100vh",
                "width": "100vw",
                "display": "flex",
                "align_items": "center",
                "justify_content": "center",
            },
        )
    )
)

print(template)
<html>
  <body>
    <div style="height:100vh;width:100vw;display:flex;align-items:center;justify-content:center">Hello, World!</div>
  </body>
</html>

The style object get's rendered and cached at the object initialization for faster template rendering.

CSSObject

Using style object is not the only way to develop CSS with PH7, You can utilise a special class called CSSObject to define stylesheets.

from ph7 import CSSObject, include
from ph7.html import body, div, head, html


class flex_center(CSSObject):
    display = "flex"
    align_items = "center"
    justify_content = "center"


template = html(
    head(
        include(flex_center),
    ),
    body(
        div(
            div(
                "Hello, World!",
            ),
            class_name=[flex_center],
        )
    ),
)

print(template)
<html>
  <head>
    <style>
      .flex-center {
        display: flex;
        align-items: center;
        justify-content: center;
      }
    </style>
  </head>
  <body>
    <div class="flex-center">
      <div>Hello, World!</div>
    </div>
  </body>
</html>

A CSSObject can also be reused via class inheritance. You can define a base CSS class and reuse it however many times you like.

from ph7 import CSSObject


class flex_center(CSSObject):
    display = "flex"
    align_items = "center"
    justify_content = "center"


class textbox(flex_center):
    height = "100vh"
    width = "100vw"


print(textbox())
.textbox {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100vw;
}

Furthermore CSSObject also allows for nesting by sub classes.

from ph7 import CSSObject


class flex_center(CSSObject):
    display = "flex"
    align_items = "center"
    justify_content = "center"


class textbox(flex_center):
    height = "100vh"
    width = "100vw"

    class text(CSSObject):
        font_size = "12px"
        font_weight = "500"
        font_family = "Lucida Console, Monaco, monospace"


print(textbox())
.textbox {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100vw;
}
.textbox .text {
  font-size: 12px;
  font-weight: 500;
  font-family: Lucida Console, Monaco, monospace;
}

To make your styles more manageable and reusable, you can define the styles in a separate module and import them throughout your codebase. Following section provides an example of a reusable stylesheet module.

Pseudo Classes and Elements

A pseudo class can be defined by adding _ at the beginning of class name, for selecting a child you can set child parameter. For pseudo, elements add __ at the beginning of the class name.

from ph7 import CSSObject


class item(CSSObject):
    height = "30px"
    width = "100%"

    margin_top = "5px"

    class _nth_child(CSSObject, n=1):
        margin_top = "0px"

    class __before(CSSObject):
        content = '">"'


print(item())
.item {
  height: 30px;
  width: 100%;
  margin-top: 5px;
}
.item::before {
  content: ">";
}
.item:nth-child(1) {
  margin-top: 0px;
}

Static Context

PH7 has a runtime context object which can be used for managing the static resource. To use a static context, import ph7.context.ctx, add ctx.static.view(__name__) at the top of your template and add ctx.static.include in your view. In the following example we'll use an external stylesheet for styling our view.

from examples.script import alertHello
from examples.style import textbox
from ph7.context import ctx
from ph7.html import body, div, head, html

ctx.static.view(__name__)


template = html(
    head(
        ctx.static.include,
    ),
    body(
        div(
            div(
                "Click Here",
                class_name=[textbox.text],
                on={
                    "click": alertHello("John Doe"),
                },
            ),
            class_name=[textbox],
        )
    ),
)

print(template.render(context={"_view": __name__}))
<html>
  <head>
    <style id="css.examples.style">
      .textbox {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100vh;
        width: 100vw;
      }
      .textbox .text {
        font-size: 12px;
        font-weight: 500;
        font-family: Lucida Console, Monaco, monospace;
      }
    </style>
    <script type="text/javascript" id="js.examples.script">
      function alertHello(user) {
        alert('Hello, ' + user);
      }
    </script>
  </head>
  <body>
    <div class="textbox">
      <div class="text" onclick="alertHello('John Doe')">Click Here</div>
    </div>
  </body>
</html>

As you can see, the static context collects the various static resources and includes them as part of the view. The output above is produced with the mode set to development by exporting DEVELOPMENT="1". When not in development mode, PH7 will compile static resources, write them as files and reference those files. Here's and example of production render of the same template

<html>
  <head>
    <link href="/static/css/examples_style.css" rel="stylesheet" id="css.examples.style" />
    <script src="/static/js/examples_script.js" type="text/javascript" id="js.examples.script"></script>
  </head>
  <body>
    <div class="textbox">
      <div class="text" onclick="alertHello('John Doe')">Click Here</div>
    </div>
  </body>
</html>

And here's what the CSS file looks like.

$ cat static/css/examples_style.css
.textbox {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  width: 100vw;
}
.textbox .text {
  font-size: 12px;
  font-weight: 500;
  font-family: Lucida Console, Monaco, monospace;
}