How Do I Fix the NativeScript CSS Error ‘require’ First Parameter Should Be String

When I first started adding platform-specific styles in my NativeScript Angular app, I ran into an error that looked pretty scary:

JS: Error: /app.component.common.css does not start with /data/data/org.nativescript.portalestapp/files/app
JS: Error: Could not load CSS from /app.component.common.css: Error: require's first parameter should be string

My Android CSS seemed to be working, but my shared common.css wasn’t. After some debugging, I realized the problem wasn’t with NativeScript itself it was with how I named and imported my CSS files. In this post, I’ll walk through what went wrong, how I fixed it, and some extra enhancements I added to make styling more flexible.

My Original Setup

I had the following files in my project:

  • app.component.html
  • app.component.ts
  • app.component.common.css
  • app.component.android.css
  • app.component.ios.css

Here’s what the code looked like:

app.component.ts

@Component({
    selector: "ns-app",
    moduleId: module.id,
    templateUrl: "app.component.html",
    styleUrls: ["./app.component.css"]
})

app.component.common.css

.page {
    background-color: #F4F5F7;
    font-family: Poppins-Regular, Poppins;
}

.custom-action-bar {
    background-color: transparent;
}

app.component.android.css

@import "/app.component.common.css";

.page {
    background-color: #fffffffa;
}

Understanding the Error

After digging deeper, I found there were two separate issues.

  1. Filename mismatch in styleUrls
    I was telling Angular to load ./app.component.css, but my shared file was named app.component.common.css. Since that file didn’t exist under the expected name, NativeScript threw the “require’s first parameter should be string” error.
  2. Incorrect @import path
    In my Android CSS I used: @import "/app.component.common.css"; The leading / means “absolute device path,” not “relative to the app bundle.” So NativeScript looked in the wrong place and failed.

The fix: match the filenames properly, and use a relative (./) or app-root (~/) import path—never a plain /.

The Clean Fix

Option A: Rename the shared file to match styleUrls

I renamed app.component.common.css to app.component.css. That way the reference in styleUrls matched the actual file.

app.component.ts

@Component({
  selector: "ns-app",
  moduleId: module.id,
  templateUrl: "app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {}

app.component.css (shared)

.page {
  background-color: #F4F5F7;
  font-family: Poppins-Regular, Poppins;
}

.custom-action-bar {
  background-color: transparent;
}

app.component.android.css

@import "./app.component.css";

.page {
  background-color: #fffffffa;
}

app.component.ios.css

@import "./app.component.css";

/* iOS-specific tweaks here */

Option B: Keep the .common name

If I really wanted to keep .common, I had to update both the component and the imports:

  • In app.component.ts:
    styleUrls: ["./app.component.common.css"]
  • In platform CSS files:
    @import "./app.component.common.css"

Extra Practice and Enhancement

Once I solved the error, I wanted to push my project a little further. Here are some fun, practical things I added.

Light/Dark Theme Toggle

I added a simple button to switch between light and dark themes at runtime.

app.component.html

<ActionBar class="custom-action-bar" title="Demo"></ActionBar>

<GridLayout rows="auto, *" class="page">
  <Button row="0" text="Toggle Theme" (tap)="toggleTheme()"></Button>

  <StackLayout row="1">
    <Label text="Hello NativeScript!" class="headline"></Label>
    <Label text="This is a themed page." class="body"></Label>
  </StackLayout>
</GridLayout>

app.component.ts

import { Component } from "@angular/core";
import { Application } from "@nativescript/core";

@Component({
  selector: "ns-app",
  moduleId: module.id,
  templateUrl: "app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  private dark = false;

  toggleTheme() {
    this.dark = !this.dark;
    const rootView = Application.getRootView();
    if (rootView) {
      rootView.className = (rootView.className || "")
        .replace(/\bis-dark\b/g, "")
        .replace(/\bis-light\b/g, "")
        .trim();
      rootView.className += (this.dark ? " is-dark" : " is-light");
    }
  }

  ngOnInit() {
    const rootView = Application.getRootView();
    if (rootView && !/\bis-(dark|light)\b/.test(rootView.className || "")) {
      rootView.className = ((rootView.className || "") + " is-light").trim();
    }
  }
}

app.component.css

.page { background-color: #F4F5F7; font-family: Poppins-Regular, Poppins; }
.custom-action-bar { background-color: transparent; }

.headline { font-size: 22; font-weight: 600; }
.body { font-size: 16; opacity: 0.9; }

/* Theme modifiers */
.is-light .page { background-color: #F7F8FA; }
.is-dark .page { background-color: #1E1F23; }

.is-light .headline, .is-light .body { color: #1a1a1a; }
.is-dark  .headline, .is-dark  .body { color: #f5f5f5; }

Now I could switch themes with one tap.

Platform Helper Classes

I added a class (is-android or is-ios) to the root view, so I could style elements more flexibly.

app.component.ts (ngOnInit)

import { Device, Application } from "@nativescript/core";

ngOnInit() {
  const rootView = Application.getRootView();
  if (rootView) {
    const extras = Device.os.toLowerCase() === "android" ? " is-android" : " is-ios";
    rootView.className = ((rootView.className || "") + extras).trim();
  }
}

app.component.css

.is-android .headline { letter-spacing: 0.2; }
.is-ios .headline { letter-spacing: 0.1; }

Safer Font Fallback

I also improved font handling with fallbacks:

.page {
  font-family: Poppins-Regular, Poppins, "SF Pro Text", "Roboto", "Helvetica Neue", Arial, sans-serif;
}

Debugging Helpers

For layout debugging, I created a temporary stylesheet:

debug.css

* { border-width: 1; border-color: rgba(0,0,0,0.05); }

And imported it when I needed visual borders:

@import "./debug.css";

Final Thought

What I learned from this little bug is simple: naming and import paths matter. NativeScript is strict about how it resolves files. If the filenames don’t match or the import path is off, you’ll end up with errors like “require’s first parameter should be string.”

Once I corrected my file naming and used relative imports, everything worked perfectly. On top of that, adding theme toggles, platform helpers, and safer font fallbacks made my app styling much more powerful.

Related blog posts