Using CSS external stylesheets - Is this possible?

I’m important a course that originated as static html. I’ve built the course.xml and linked to the source html files.

Here’s where I’m stuck. The formatting is heavily reliant on the css style sheet. I uploaded it to /static within the course, and referenced it in the head of each html file. BUT edx is stripping off the entire section which breaks the css. And this also means I can’t embed the css into the source html files either. I scoured the docs, this site, web searches and found nothing so far.

How can I implement the css stylesheet? (if it’s even possible)

Hey @fotmasta

Thanks for posting, I have few doubts, what do you really want to customize? A single course or LMS, what are the customizations you are looking for?

Thanks

Thank you for replying. I have a single course to customize.
They want to customize using a CSS style sheet for the headings, indentation, and other formatting.

@fotmasta, there is this OEP about functionality that would provide course-wide HTML overrides, but its status has been “Provisional” for the last 4 years. At the moment, there are some other ways to achieve this, though:

  1. Creating a separate site with a comprehensive theme. To do this, you would need to:

    1. Create a comprehensive theme with desired overrides.
    2. Set up a new Site.
    3. Set the Site’s theme.
    4. Set the course_org_filter option to display only this specific course on the new Site.

    This way, the whole site will have a custom theme, but it will be available on a separate domain.

  2. This workaround is described here. Basically, you can embed the styling directly in XBlocks on each course page. For example, you can add the following HTML XBlock to a unit to override the page’s body:

    <style>
      .course-wrapper {
        background-color: red !important;
      }
    </style>
    

    This will apply only to pages that contain these XBlocks, so other parts like the Course Outline page or Discussions will not be altered.

1 Like

That workaround looks pretty good. I might be able to copy the guts of the master css file and insert it into the head of all the html files.

Thank you!

@fotmasta, I’ve just found that we have implemented OEP-15 and merged it into the edX master branch shortly after my last comment. You can now define custom CSS and JS resources in the course advanced settings in Studio.

If you are using Koa, then we have also internally backported this feature there. Feel free to use our opencraft-release/koa.3 branch if you’d like.

Hi, I have tried to add a custom wide CSS in the advanced settings in the Studio but I don’t see my custom CSS loaded in any page (even after restarting the platform). Do I need to do something else for my changes to take effect (e.g. clear cache)? I could not find any specific instructions anywhere about this topic (most existing articles are about large-scale theming). I use the tutor version of open edx.

Hi @gxexakis, it seems that the final implementation had a few changes that were not updated in the linked OEP yet. The most important change is that additional resources should be simply provided as a list (without defining “global_scripts”). You don’t need to restart the platform after adding them in “Advanced Settings”. Clearing the browser’s cache might be helpful in some cases, though.

You can find the list of discrepancies here or read the updated version of this document here.

2 Likes

Thank you for your reply, works well now :)!

Hi, I need some more guidance on loading custom CSS files. I am trying to add a Custom CSS file to my Advance Settings but I do not see the CSS implemented. I am not sure where I am having the issue.

  • Is there specifications/ limitations to where the file should be located? I have the custom.css file in a GIT repository.
  • I have mostly classes that I want to implement. Is there any limitations to this?

Any help will be appreciated.

Am I correct in thinking the feature has nothing to do about Learning MFE (any MFE at all). Just the legacy UI is affected with it?

@bergman, partially. It is correct that this has nothing to do with the MFEs. However, XBlocks are rendered directly by the LMS, so the styling is applied to them. The learning MFE only displays the XBlocks within an iframe.

But… Doesn’t xBlock’s iframe render its own fragment html (+css, +js) piece exclusively?
Those custom CSS/JS are included into parental legacy page. They never appear in parental MFE page, I think?

@bergman, I’m unsure if I understand your question correctly, so I’ll describe the current behavior. To use this feature:

  1. Create test.css with the following content:
    * {
      background: red !important;
    }
    
  2. In Studio, go to “Content → Files & Uploads” and add the CSS file.
  3. Go to “Settings → Advanced Settings” and add your resource to the list (e.g., ["/asset-v1:edX+DemoX+Demo_Course+type@asset+block@test.css"]).
  4. Visit some unit in the Preview; it should look like this:
  5. Visit the same unit in the Learning MFE; it should look like this:

In the legacy experience, XBlocks were rendered directly on the same page.
In the Learning MFE, they are still rendered by the LMS, so they must be displayed in an iframe. Therefore, you can apply the course-wide styles to XBlocks, but not to the rest of the page.

1 Like

@Agrendalath (& Everyone)

Thank you for posting this!

Can we place the CSS file into the 'File & Uploads" of one course and use that as a ‘global CSS’ file host for many courses? So using your example we would add the files web path:

[“https://yourname.edx.org/asset-v1:edX+DemoX+Demo_Course+type@asset+block@test.css”]

Is this the best solution to have one place for a global CSS file for many courses? OR can we host the CSS file on Github instead? We are looking for the solution most unlikely to go wrong.

We are currently adding a RAW HTML component on every page with a ‘link stylesheet=’ to the Advanced Settings. We have to do this on every page, which isn’t a problem but we just want to know what is the most robust solution before we build out lots of classes.

Thank you for helping!

@Southcoastbeach, yes, you can use the full URL to a course asset, as shown in this example.

Is this the best solution to have one place for a global CSS file for many courses?

It should be good enough for most typical scenarios.

Hi,

we tried your procedure with the following css. Then we add the css to each html page of the course with:

<head>
  <link rel="stylesheet" href="/static/unit.css">
</head>

And in the studio it looks as expected. But as soon as we switch to live view the css is somehow overwritten.

/* Static CSS File (styles.css) */

/* Importing custom font */

  @font-face {
    font-family: 'Futura';
    src: url('Futura_PT_Light.otf') format('opentype') !important;
    font-weight: 300; /* Normal */
    font-style: normal;
  }
  
  @font-face {
    font-family: 'Futura';
    src: url('Futura_PT_Medium.otf') format('opentype') !important;
    font-weight: 450; /* Demi-bold */
    font-style: normal;
  }

  @font-face {
    font-family: 'Futura';
    src: url('fonts_futura/Futura_PT_Demi.otf') format('opentype') !important;
    font-weight: 500; /* Bold */
    font-style: normal;
  }

/* General page styling */
body {
    font-family: 'Futura', sans-serif !important;
    background-color: #efefef !important;
    color: #333 !important;
    margin: 20px !important;
    line-height: 1.6 !important;
  }
  
  /* Header styles */
  body h1, h2, h3 {
    font-family: 'Futura', sans-serif !important;
    color: rgb(0, 0, 0) !important;
  }
  
  body h1 {
    color: rgb(57, 164, 146) !important;
    font-size: 3rem !important;
    margin-bottom: 20px !important;
    font-weight: 500 !important;
  }
  
  body h2 {
    font-size: 2.25rem !important;
    margin-top: 20px !important;
    font-weight: 500 !important;
  }
  
  body h3 {
    font-size: 1.8rem !important;
    margin-top: 15px !important;
    font-weight: 500 !important;
  }
  
  /* Paragraph and list styles */
  body p, li {
    font-size: 1.5rem !important;
    font-weight: 400 !important;
    margin-top: 2px !important;
    margin-bottom: 2px !important;
  }
  

  /* List styling */
  body ul {
    margin-left: 20px !important;
    padding-left: 0 !important;
  }
  
  /* Link styling */
  a {
    color: #0056b3 !important;
    text-decoration: none !important;
  }
  
  a:hover {
    text-decoration: underline !important;
  }
  
  /* Section styling */
  .section {
    margin-bottom: 30px !important;
  }
  
  
  /* Style the image container */
  .image-container {
    position: relative !important;
    display: inline-block !important;
  }
  
  /* Hoverable region styles */
  .hover-region {
    position: absolute !important;
    border: 2px solid transparent !important; /* Invisible border */
    cursor: pointer !important;
    transition: border-color 0.3s !important; /* Smooth transition for highlighting */
  }
  
  /* Highlighted region */
  .highlight {
    border-color: #f00; /* Red border when highlighted */
  }
  
  /* Explanation container */
  .explanation {
    background-color: #f0f0f0 !important;
    padding: 10px !important;
    margin-top: 20px !important;
    margin-bottom: 20px !important;
    border: 1px solid #888 !important;
    transition: background-color 0.3s, box-shadow 0.3s ease-in-out !important; /* Smooth transition for background and shadow */
  }
  
  /* Highlight the explanation on hover */
  .explanation:hover {
    background-color: rgb(57, 164, 146) !important; /* Highlight color */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) !important; /* Subtle shadow effect */
  }
  
  /* Headings inside explanations */
  .explanation h4 {
    font-size: 1.25rem !important;
    margin-bottom: 10px !important;
    color: #444 !important; /* Color for headings */
  }
  
  /* Paragraph styling inside explanations */
  .explanation p {
    font-size: 1rem !important;
    color: #555 !important; /* Color for paragraphs */
  }