Color-coding based on field content

I want to style a field in Anki in which German articles are shown (der, die, das), and style it, so it shows blue for ´der´, red for ´die´and green for ´das´. I am using the desktop app and a basic note card type in anki, and display the articles on the back of the card.

I currently have 5 fields: Front > English, Back > Article, Singular, Plural, Image

This basic note has Front Template, Back Template and Styling sections. I pasted the code below in the Back Template section.

I tried this code:

Back Template: {{FrontSide}}

<hr id=answer>

<style>
  .derClass { color: blue; }
  .dieClass { color: red; }
  .dasClass { color: green; }
</style>

<div style='font-family: "Arial"; font-size: 25px;'>
  <span class="{{#eq ARTICLE 'der'}}{{class 'derClass'}}{{/eq}}
          {{#eq ARTICLE 'die'}}{{class 'dieClass'}}{{/eq}}
          {{#eq ARTICLE 'das'}}{{class 'dasClass'}}{{/eq}}">

    {{ARTICLE}}

  </span>
  <span class="{{#eq ARTICLE 'der'}}{{class 'derClass'}}{{/eq}}
          {{#eq ARTICLE 'die'}}{{class 'dieClass'}}{{/eq}}
          {{#eq ARTICLE 'das'}}{{class 'dasClass'}}{{/eq}}">

    {{SINGULAR}}

  </span>
</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PLURAL}}</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PHOTO}}</div>

"Styling": .card {
    font-family: arial;
    font-size: 20px;
    text-align: center;
    color: black;
    background-color: white;
}

And got this answer of why it does not work:
Back template has a problem:
Found ‘⁨{{/eq}}⁩’, but expected ‘⁨{{/eq ARTICLE ‘der’}}⁩’

When I add the corresponding tags: /eq ARTICLE 'der, /eq ARTICLE 'die and /eq ARTICLE 'das, the problem persists and the error message does not change.

What am I doing wrong?

I think you are trying to use mustache template fragments in anki, but anki does not support that. You can learn more about anki field replacements here: Field Replacements - Anki Manual

Instead you can check for articles used on your card in javascript. Something like this should do the job:

<script>document.querySelector(".card").classList.add(`{{ARTICLE}}`.trim().toLowerCase()+"Class")</script>
.derClass{color:green}
2 Likes

I gave this code a try @NielegalneApfelschor, and it only displayed the first card in color, and then all in black. I also tried a workaround (second code) and it didn´t display any color at all. How come such a basic feature is so hard to implement? :slight_smile:

{{FrontSide}}

<hr id=answer>

<style>
  .derClass { color: blue; }
  .dieClass { color: red; }
  .dasClass { color: green; }
</style>

<div class="card">  <span class="article-content">{{ARTICLE}}</span>
  <span class="singular-content">{{SINGULAR}}</span>
</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PLURAL}}</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PHOTO}}</div>

<script>
const observeContainer = document.querySelector(".card");
const observer = new MutationObserver(mutations => {
  for (const mutation of mutations) {
    if (mutation.type === "childList") {
      colorCards();
    }
  }
});

function colorCards() {
  const articleElements = document.querySelectorAll(".article-content");
  const singularElements = document.querySelectorAll(".singular-content");

  for (let i = 0; i < articleElements.length; i++) {
    const articleElement = articleElements[i];
    const singularElement = singularElements[i];

    articleElement.textContent = articleElement.textContent.trim().toLowerCase();  // Ensure lowercase article
    const article = articleElement.textContent;
    const colorClass = `${article}Class`;

    articleElement.style.color = colorClass;  // Option 2 (Direct Coloring)
    singularElement.classList.add(colorClass);
  }
}

colorCards();  // Initial call to color the first card
observer.observe(observeContainer, { childList: true });
</script>

and
Improved MutationObserver Timing:

Modifed script to address the potential timing issue with the MutationObserver. Here’s an updated version:

Back Template: {{FrontSide}}

<hr id=answer>

<style>
  .derClass { color: blue; }
  .dieClass { color: red; }
  .dasClass { color: green; }
</style>

<div class="card">  <span class="article-content">{{ARTICLE}}</span>
  <span class="singular-content"></span>
</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PLURAL}}</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PHOTO}}</div>

<script>
const observeContainer = document.querySelector(".card");

// MutationObserver callback with mutation check
const mutationCallback = (mutations) => {
  for (const mutation of mutations) {
    if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
      colorCards();
    }
  }
};

// Improved colorCards call - check for added nodes
function colorCards() {
  const articleElement = document.querySelector(".article-content");
  const singularElement = document.querySelector(".singular-content");

  if (articleElement) {  // Ensure element exists
    articleElement.textContent = articleElement.textContent.trim().toLowerCase();
    const article = articleElement.textContent;
    const colorClass = `${article}Class`;

    articleElement.style.color = colorClass;  // Option 2 (Direct Coloring)
    singularElement.classList.add(colorClass);
  }
}

const observer = new MutationObserver(mutationCallback);
observer.observe(observeContainer, { childList: true });

// Call colorCards initially (optional)
colorCards();
</script>

"Styling": .card {
    font-family: arial;
    font-size: 20px;
    text-align: center;
    color: black;
    background-color: white;
}

Do you know what you are trying to use? You don’t need a mutation observer as the script you have on your card templates gets re-run every time a card gets show.

card renderer seems to reset classes sometimes after executing the javascript. Adding a short delay fixes it:

<script>(async()=>{
await new Promise(r => setTimeout(r, 5));
document.querySelector(".card").classList.add(`{{Reading}}`.trim().toLowerCase()+"Class")
})()</script>

Also remember to add styles to other articles (.dieClass, .dasClass) with your chosen colors.

Also, you are obviously using an AI chat bot that has no idea on how anki card rendering works. It would be helpful if you said so in your first post.

3 Likes

Why not just put {{ ARTICLE }} in the class attribute, like this?

<span class="article {{ ARTICLE }}">...

And change CSS to:

.article.der { color: blue ; }

etc. (The .article class is totally optional, I think it’s easier to read like that)

1 Like

Working code

{{FrontSide}}

<hr id=answer>

<style>
  .derClass { color: blue; }
  .dieClass { color: red; }
  .dasClass { color: green; }
</style>

<div class="card">  <span class="article-content">{{ARTICLE}}</span>
  <span class="singular-content">{{SINGULAR}}</span>
</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PLURAL}}</div>

<div style='font-family: "Arial"; font-size: 25px;'>{{PHOTO}}</div>

<script>
(async () => {
  await new Promise(resolve => setTimeout(resolve, 5)); // Introduce a short delay

  const observeContainer = document.querySelector(".card");
  const articleElement = document.querySelector(".article-content");
  const singularElement = document.querySelector(".singular-content");

  if (articleElement) {
    const article = articleElement.textContent.trim().toLowerCase();
    const colorClass = `${article}Class`;

    articleElement.classList.add(colorClass); // Add class to ARTICLE element
    singularElement.classList.add(colorClass); // Add class to SINGULAR element
  }
})();
</script>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.