Angular Signals Code Lab CSS Requires “No-Quirks” Mode

The sample application for “Getting Started with Angular Signals” is designed to run on the StackBlitz cloud-based development environment. Getting it up and running properly on my local machine (after solving installation and compilation errors) took more effort than I had expected. I wouldn’t call the experience enjoyable, but it was certainly an educational trip through all the infrastructure underlying an Angular app. Now I have all the functional components up and running, I turn my attention to the visual appearance of the app. The layout only seems to work for certain window sizes and not others. I saw a chance for me to practice my CSS layout debugging skills, but what it also taught me was “HTML quirks mode”.

The sample app was styled to resemble a small hand-held device in the vein of the original Nintendo Game Boy: a monochrome screen up top and a keyboard on the bottom. (On second thought, maybe it’s supposed to be a Blackberry.) This app didn’t have audio effects, but there’s a little fake speaker grill in the lower right for a visual finish. The green “enclosure” of this handheld device is the <body> tag of the page, styled with border-radius for its rounded corners and box-shadow to hint at 3D shape.

When things go wrong, the screen and keyboard spills over the right edge of the body. Each of which had CSS specifying a height of 47% and an almost-square aspect-ratio of 10/9. The width, then, would be a function of those two values. The fact that they become too wide and spill over the right edge means they have “too much” height for the specified aspect ratio.

Working my way up the component tree, I found the source of “too much” height was the body tag, which has CSS specifying a width (clamped within a range) and an aspect-ratio of 10/17. The height, then, should be a function of those two values. When things go wrong, the width seems to be clamped to maximum of specified range as expected, but the body is too tall. Something has taken precedence over aspect-ratio:10/17 but that’s where I got stuck: I couldn’t figure out what the CSS layout system had decided was more important than maintaining aspect ratio.

After failing to find an explanation on my own, I turned to the StackBlitz example which worked correctly. Since I’ve learned the online StackBlitz example isn’t exactly the same as the GitHub repository, the first thing I did is to compare CSS. They seemed to match minus the syntax errors I had to fix locally, so that’s not it. I had a hypothesis that StackBlitz has something in their IDE page hierarchy and that’s why it worked in the preview pane. But clicking “Open in new tab” to run the app independent of the rest of StackBlitz IDE HTML still looks fine. Inspecting the object tree and associated stylesheets side-by-side, I saw that my local copy seems to have duplicated styles. But since that just meant one copy completely overrides the other identical copy, it wouldn’t be the explanation.

The next difference I noticed between StackBlitz and local copy is the HTML document type declaration at the top of index.html.

<!DOCTYPE html>

This is absent from project source code, but StackBlitz added it to the root when it opened the app in a new tab. I doubted it had anything to do with my problem because it isn’t a CSS declaration. But in the interest of eliminating differences between them, I added <!DOCTYPE html> to the top of my index.html.

I was amazed to find that was the key. CSS layout now respects aspect-ratio and constrains height of the body, which kept screen and keyboard from spilling over. But… why does the HTML document type declaration affect CSS behavior? A web search eventually led me to the answer: backwards compatibility or “Quirks Mode”. By default, browsers emulate behavior of older browsers. What are those non-standards-compliant behaviors? That is a deep dark rabbit hole I intend to avoid as much as I can. But it’s clear one or more quirks affected aspect-ratio used in this sample app. Having the HTML document type declaration at the top of my HTML activates the “no-quirks” mode that intends to strictly adhere to modern HTML and CSS standards, and now layout works as intended.

The moral of today’s story: Remember to put <!DOCTYPE html> at the top of my index.html for every web app project. If things go wrong, at least the mistake is likely my own fault. Without the tag, there are intentional weirdness because some old browser got things wrong years ago and I don’t want that to mess me up. (Again.)

Right now, I have a hard enough time getting CSS to do my bidding for normal things. Long term, I want to become familiar enough with CSS to make it do not just functional but also fun decorative things.


My code changes are made in my fork of the code lab repository in branch signals-get-started.

CSS Beginner Struggles: aspect-ratio and height

Reviewing CSS from web.dev’s “Learn CSS!” course provided a refresher on a lot of material and also introduced me to new material I hadn’t seen before. I had hoped for a bit of “aha” insight to help me with CSS struggles in my project, but that didn’t happen. The closest was a particular piece of information (Flexbox for laying out along one dimension, Grid for two dimensions) that told me I’m on the right track using Flexbox.

A recurring theme with my CSS frustration is the fact height and width are not treated the same way in HTML layout. I like to think of them as peers, two equal and orthogonal dimensions, but that’s not how things work here. It traces back to HTML fundamentals of laying out text for reading text in a left-to-right, top-to bottom languages like English. Like a typesetter, the layout is specified in terms of width. Column width, margin width, etc. Those were the parameters that fed into layout. Height of a paragraph is then determined by the length of text that could fit within specified width. Thus, height is an output result, not an input parameter, of the layout process.

For my Compass web app, I had a few text elements I knew I wanted to lay out. Header, footer, sensor values, etc. After they have all been allocated screen real estate, I wanted my compass needle to be the largest square that could fit within the remaining space. That last part is the problem: while we have ways to denote “all remaining space” for width, there’s no such equivalent for height because height is a function of width and content. This results in unresolvable circular logic when my content (square compass) is a function of height, but the height is a function of my content.

I could get most of the way to my goal with liberal application of “height: 100%” in my CSS rules. It does not appear to inherit/cascade, so I have to specify “height: 100%” on every element down the DOM hierarchy. If I don’t, height of that element collapses to zero because my compass doesn’t have an inherent height of its own.

Once I get to my compass, I could declare it to be a square with aspect-ratio. But when I did so, I find that aspect-ratio does its magic by changing element height to satisfy specified aspect ratio. When my remaining space is wider than it is tall, aspect-ratio expands height so it matches width. This is consistent with how the rest of HTML layout treats width vs. height, and it accomplishes the specified aspect ratio. But now it is too tall to fit within remaining space!

Trying to reign that in, I played with “height: 100%“, “max-height: 100%“, and varying combinations of similar CSS rules. They could affect CSS-specified height values, but seems to have no effect on height change from aspect-ratio. Setting aspect-ratio means height is changed to fit available width and I found no way to declare the reverse in CSS: change width to fit within available height.

From web.dev I saw Codepen.io offered ability to have code snippets in a webpage, so here’s a test to see how it works on my own blog. I pulled the HTML, CSS, and minimal JavaScript representing a Three.js <canvas> into a pen so I could fiddle with this specific problem independent of the rest of the app. I think I’ve embedded it below but here’s a link if the embed doesn’t work.

After preserving a snapshot of my headache in Codepen, I returned to Compass app which still had a problem that needed solving. Unable to express my intent via CSS, I turned to code. I abandoned using aspect-ratio and resized my Three.js canvas to a square whose size is calculated via:

Math.floor(Math.min(clientWidth, clientHeight));

Taking width or height, whichever is smaller, and then rounding down. I have to round down to the nearest whole number otherwise scroll bars pop up, and I don’t want scroll bars. I hate solving a layout problem with code, but it’ll have to do for now. Hopefully sometime in the future I will have a better grasp of CSS and can write the proper stylesheet to accomplish my goal. In the meantime, I look for other ways to make layout more predictable such as making my app full screen.


The source code for my project is publicly available on GitHub, though it no longer uses aspect-ratio as per the workaround described at the end of this poist.

Basic Motor Test for SGVHAK Rover

Our first opportunity to deploy the new Bootstrap-based touch-friendly HTML UI was a basic but critical motor test. A RoboClaw motor controller utilizes encoder feedback to know what the motor is doing. Based on this feedback, logic within the controller adjusts its electrical output to deliver either a commanded velocity or a commanded position. For any of that to work, an encoder must be installed properly. Our rover’s travelling wheel motors incorporated a pair of LED+photo diode units as optical quadrature encoders. Since we have a pair of sensors, there are two possible ways to wire them to RoboClaw input: one of which is correct and other is backwards.

To verify wiring, we need a basic motor test that will instruct RoboClaw to drive its motor at some power level, which is something it can do without encoder input. Then the test will query for encoder count and verify positive motor motion increments encoder count. If positive motion decrements encoder count, we’ll need to swap some wires.

Which wires need swapping? That depends on which way our motor is turning. We want positive motor rotation to correspond to forward rover motion, which means the left and right sides of the rover will be wired in mirror image. For rover’s right side wheels, positive motion will be clockwise (when viewed from rover’s right) and rover left wheels will be counter-clockwise. This desire to see the wheel motion in context of rover chassis is why we wanted this motor test to be usable on board the rover itself via the Raspberry Pi touchscreen.

If positive motor motion is rotating in the direction we want, and we need to swap wires, then we swap the encoder wires to maintain motor direction. If we need to swap wires and our motor is spinning in the wrong direction, we leave the encoder wires alone and swap our motor control wires instead. If the direction is wrong, and encoder is in sync, we’ll need to swap both sets of wires.

Basic Motor Test

HTML UI work described in this post began with this commit visible on Github.

Make RoboClaw HTML Control UI Scale Across Different Screen Types with Bootstrap

The basic HTML UI we were using to learn how to work with a RoboClaw motion controller was bare-bones web 1.0 in style. This worked very well when it only had to let us experiment to understand the controller while it’s sitting on a test stand next to the development workstation computer.

Once we got ready to move beyond tethered desktop computer scenarios, though, we had a problem. We had two touchscreen scenarios: one for UI directly on the robot via the Raspberry Pi Foundation touchscreen, the second scenario is remote control using a cell phone or tablet’s web browser.

Because the UI content was written in bare HTML, it does not scale to touchscreen devices the way we expect all modern web sites to do. In order to make this happen, we had to bring our HTML from the relative stone ages to conform to current practices.

Fortunately, this project received help from someone who has recently completed training on web design and development. [Amy] volunteered to jump in and make the controller HTML presentable and usable on touchscreen devices. Thanks to the open source nature of the web, most of the hard work has already been done by others and we just need to pull in one of the many freely available libraries to help build an UI that can respond to changes in the web browser environment.

For this experiment, [Amy] pulled in Bootstrap then began retrofitting the control test UI so Bootstrap can perform its magic across the different types of screens.

 

Link in Bootstrap

Static Web Site Hosting with Amazon S3 and Route 53

aws_logoWeb application frameworks have the current spotlight, which is why I started learning Ruby on Rails to get an idea what the fuss was about. But a big framework isn’t always the right tool for the job. Sometimes it’s just a set of static files to be served upon request. No server-side smarts necessary.

This was where I found myself when I wanted to put up a little web site to document my #rxbb8 project. I just wanted to document the design & build process, and I already had registered the domain rxbb8.com. The HTML content was simple enough to create directly in a text editor and styled with CSS from the Materialize library.

After I got a basic 1.0 version of my hand-crafted site, I uploaded the HTML (and associated images) to an Amazon S3 bucket. It only takes a few clicks to allow files in a S3 bucket to be web-accessible via a long cumbersome URL on Amazon AWS domain http://rxbb8.com.s3-website-us-west-2.amazonaws.com. Since I wanted this content to be accessible via the rxbb8.com domain I already registered, I started reading up on the AWS service named in geek-humor style as Route 53.

Route 53 is designed to handle the challenges of huge web properties, distributing workload across many computers in many regions. (No single computer could handled all global traffic for, say, netflix.com.) The challenge for a novice like myself is to figure out how to pull out just the one tool I need from this huge complex Swiss army knife.

Fortunately this usage case is popular enough for Amazon to have written a dedicated developer guide for it. Unfortunately, the page doesn’t have all the details. The writer helpfully points the reader to other reference articles, but those pages revert back to talking about complex deployments and again it takes effort to distill the simple basics out of the big feature list.

If you get distracted or lost, stay focused on this Cliff Notes version:

  1. Go into Route 53 dashboard, create a Hosted Zone for the domain.
  2. In that Hosted Zone, AWS has created two record sets by default. One of them is the NS type, write down the name servers listed.
  3. Go to your domain registrar and tell them to point name servers for the domain to the AWS name servers listed in step 2.
  4. Create S3 storage bucket for the site, enable static website hosting.
  5. Create a new Record Set in the Route 53 Hosted Zone. Select “Alias” to “Yes” and point alias target to the S3 storage bucket in step 4.

Repeat #4 and #5 for each sub-domain that needs to be hosted. (The AWS documentation created example.com and repeated 4-5 for www.example.com.)

And then… wait.

The update in step 3 needs time to propagate to name servers across the internet. My registrar said it may take up to 24 hours. In my case, I started getting intermittent results within 2 hours, but it took more than 12 hours before everything stabilized to the new settings.

But it was worth the effort to see version 1.0 of my created-from-scratch static web site up and running on my domain! And since it’s such a small and simple site with little traffic, it will cost me only a few pennies per month to host in this manner.

 

Let the App… Materialize!

materializecsslogoAfter I got the Google sign-in working well enough for my Rails practice web app, the first order of business was to build the basic skeleton. This was a great practice exercise to take the pieces I learned in the Ruby on Rails Tutorial sample app and build something of my own design.

The initial pass implemented basic functionality but it didn’t look very appealing. I had focused on the Rails server-side code and left the client-side code simple plain HTML that would have been state-of-the-art in… maybe 1992?

Let’s make it look like something that belongs in 2017.

The Rails tutorial sample app used Bootstrap to improve the appearance and functionality of the client-side interface. I decided to take this opportunity to learn something new instead of doing the same thing. Since I’m using Google Sign-In in this app, I decided to adopt Google’s design concepts to my client-side appearance as well.

Web being the web, I knew I wouldn’t have to start from scratch. I knew about Google’s own Material Lite and thought that would be a good candidate before I learned it had been retired in favor of its successor, Material Components for the web. One of the touted advantages was improved integration with different web platforms. Sadly Rails was not among the platforms with examples ready-to-go.

I looked around for an existing project to help Rails projects adapt Google’s design language, and that’s when I found Materialize: A library that shares many usage patterns with Bootstrap. The style sheets are even written using SASS, native to default Rails apps, making for easy integration. Somebody has done that work and published it as Ruby gem materialize-sass, so all I had to do was add a single line to use Materialize in my app.

Of course I still had to put in the effort to revise all the view files in my web app to pick up Materialize styling and features. That took a few days, and the reward for this effort is a practice web app which no longer look so amateurish.

Simple Online Digital Photo Frame

The CarrierWave Playground project was created for experimentation with image upload. As intended, it helped me learn things about CarrierWave such as creating versions of the image scaled to different resolutions and extracting EXIF image metadata.

Obviously the image has to be displayed to prove that the upload was successful. I hadn’t intended to spend much time on the display side of things, but I started playing with the HTML and kept going. Logic was added for the browser to report its window size so the optimal image could be sent and scaled to fit. I had a button to reload the page, and it was fairly simple to change it from “reload the current page” to “navigate to another page”. Adding a JavaScript timer to execute this navigation… and voila! I had myself a rudimentary digital photo frame web app that loads and displays image in a sequence.

It’s fun but fairly crude. Brainstorming the possibilities, I imagine the following stages of sophistication:

Stage 1 – Basic: Where I am now, simple JavaScript that performs page navigation on a timer.

Problem: page blinks and abruptly shifts as new page is loaded. To avoid the abrupt shift, we have to eliminate the page switch.

Stage 2 – Add AJAX: Instead of a page navigation, perform a XMLHttpRequest to the server asking for information on the next image. Load the image in the background, and once complete, perform a smooth transition (fade out/fade in/etc.) from one image to the next.

Problem: Visual experience is at the mercy of the web browser, which probably has an address bar and other UI on screen. Also, the user’s screen will quickly go dark due to power saving features. To reliably solve both, I will need app-level access.

Stage 3 – Vendor-specific wrapper: Every OS platform has a way to allow web site authors an express lane into the app world. Microsoft offers the Windows App Studio. Apple has iOS web applications. Google has Android Web Apps.

Unknown: The JavaScript timer is a polling model, do we gain anything by moving to a server-push model? If so, that means…

Stage 4 – WebSocket: Photo updates are triggered by the server. Since I’m on Rails, the most obvious answer is to do this via WebSockets using Action Cable.

Looking at the list, I think I can tackle Stage 2 pretty soon if not immediately.

Stages 3 and 4 are more advanced and I’ll hold off for later.

Codecademy “Learn Sass” notes

SasslogoWhile learning Ruby on Rails, one of the things I put on my “look into this later” list was Sass. I knew it was related to CSS but didn’t know the details, I just noticed when the Rails generator created a controller, it created a .scss file under the stylesheets directory.

So when I received email from Codecademy notifying me that they have a new class on Sass… the “look into this later” became “let’s look into it now”.

Unlike Ruby on Rails, Sass is not a huge complicated system. It solves a fairly specific set of problems typical of CSS growing unwieldy as it grows with a project. It introduces some very nice concepts to keep CSS information organized. After banging my head on lots of walls with Ruby on Rails, it is refreshing to tackle a smaller-scope project and be able to understand what’s going on. The Codecademy format is well suited to teach a smaller scoped concept like Sass.

I was also mildly amused to learn that Sass is apparently written in Ruby. I don’t think it particularly matters what the implementation was, but it’s amusing to me to see Ruby applied in an entirely different way from Rails. The bonus is that, if I should try to debug or extend Sass myself, I wouldn’t be starting from scratch looking over its source code.

Being a fresh course, the Codecademy class had a few minor problems that still need to get ironed out. The flashcard example was supposed to flip on mouse hover… it never did anything for me. Too bad, because I think the effect would have been interesting.

I haven’t gotten far enough with Rails to think about making my web app pretty, but when I do, I know how to keep my style sheets manageable with Sass.

Peek under the hood of Bootstrap

After completing Codecademy’s “Make a Website” lesson, I decided to go explore a side track to look under the hood of the Bootstrap framework used in the lesson. I’m not going to dive deep (yet), but I wanted to break it down into a short list of names I expect to encounter again as I explore.

The actual run-time components of Bootstrap appears to be two Cascading Style Sheet (CSS) files and one JavaScript (JS) file. One of the two CSS files is an optional theme. This confirms that Bootstrap has no client-side requirements, just a web browser that can understand standard CSS & JS files.

On the developer side, things get more interesting.

Grunt is the build system used by the Bootstrap project to build the project code, the documentation files, and run the unit tests.

It’s not clear if the JavaScript files are worked on directly, but the CSS is definitely not. It is done with Less and compiled to CSS. Some parts in the documentation listed “Less/Sass” implying Sass is a similar thing. Maybe look into this later.

Once the product is rebuilt, the JavaScript code is automatically reviewed by JSHint. Then tests are executed in the PhantomJS headless JavaScript runtime orchestrated by QUnit testing framework for JavaScript.

The product documentation pages were generated by Jekyall. Don’t know what the input for Jekyall would look like, but the output is static HTML pages. It claims to be the engine behind GitHub pages, so I know I’ll run into this again when I explore GitHub.

Several package managers were listed. Looks like NPM is required for actually working on Bootstrap itself, though it can also be used for projects consuming Bootstrap. Bower and Composer are two other package managers that seem to apply only to Bootstrap consumers.

That’s the first cut. Some things are still fuzzy, and some things I thought were clear may actually be wrong. We’ll see!

Codecademy “Make a Website” notes

I’ve just completed the “Make a Website” lesson on Codecademy, because it made sense to start at the beginning and (re)learn the fundamentals. I knew some simple HTML going in so I had expected part of it to be review and part of it to be new material.

The review part was expected: the lesson went over basic concepts of HTML tags and their hierarchical structure, then went into fine-tuning appearance via CSS.

But the new material was a surprise. After the CSS unit completed teaching about backgrounds and borders and spacing, it promised the next unit is about content and page layout. I thought “OK, good, now we’re getting into stuff I don’t know.”

The next unit began by introducing the Bootstrap framework to manage page layout. It was still an informative and fun interactive lesson, but I was left disappointed by the departure from HTML fundamentals.

It felt incomplete, like a math class that skipped doing addition with pencil and paper and instead going straight to using a calculator. Yeah, I’m probably not going to do it by hand ever again, but I wanted a lesson to teach me how to do it at least once. I would have preferred the lesson to go a bit into doing HTML layout the hard way, then say “Now that you know how to do it the hard way, let’s do it the easy way with Bootstrap.” Doing it both ways would give me a better feel of how HTML layout works and how Bootstrap makes it easier.

The Codecademy lesson worked as advertised, I’ll just have to fill this hole in my knowledge with something else.