Style an ordered list with Cyrillic letters

2019-01-28 02:03发布

问题:

There are many possible values for list-style-type CSS property (e. g. decimal, lower-latin, upper-greek and so on). However there are none for the Cyrillic alphabet (which, btw, has different variations for different languages).

What is the best way to style an ordered list with Cyrillic letters?

(I'm providing a solution I ended up with despite I'm not very happy with it.)

回答1:

I know nothing about Cyrillic list schemes so I’m at risk of a bit of cultural embarrassment here, but CSS3 Lists module (still in working draft) defines quite a few Cyrillic alphabetic list types: lower-belorussian, lower-bulgarian, lower-macedonian, lower-russian, lower-russian-full, lower-serbo-croatian, lower-ukrainian, lower-ukrainian-full, upper-belorussian, upper-bulgarian, upper-macedonian, upper-russian, upper-russian-full, upper-serbo-croatian, upper-ukrainian, upper-ukrainian-full. As expected, the state of support for these is deplorable currently (certainly nothing in Gecko or WebKit), but hopefully going forwards these will start to be implemented.

Update: some changes have been made – the definition of list types has been moved into the CSS3 Counter Styles module whose current draft (Feb 2015) has unfortunately lost all alphabetical Cyrillic types. This is in Candidate Recommendation stage so it’s unlikely that additions will be made at the point. Perhaps in CSS4 List Styles?



回答2:

In this method I'm using CSS-generated content in before each list item.

.lower-ukrainian {
  list-style-type: none;
}

.lower-ukrainian li:before {
  display: inline-block;
  margin-left: -1.5em;
  margin-right: .55em;
  text-align: right;
  width: .95em;
}

.lower-ukrainian li:first-child:before {
  content: "а.";
}

.lower-ukrainian li:nth-child(2):before {
  content: "б.";
}

/* and so on */

Disadvantages

  1. Hardcoded, restrict list to a certain max length.
  2. Not pixel-perfect as compared to a regular order list


回答3:

I'm surprised that there is no Cyrillic numbering. Here's a quick JS solution for you:

function base_convert(n, base) {
    var dictionary = '0123456789abcdefghijklmnopqrstuvwxyz';
    var m = n.toString(base);
    var digits = [];

    for (var i = 0; i < m.length; i++) {
        digits.push(dictionary.indexOf(m.charAt(i)) - 1);
    }

    return digits;
}

var letters = {
    'russian': {
        'lower': 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя',
        'upper': 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
    }
}

$('ul, ol').each(function() {
    if (!(results = $(this).prop('class').match(/(upper|lower)-([a-z]+)/i))) return;

    var characters = letters[results[2]][results[1]];

    $('> li', this).each(function(index, element) {
        var number = '', converted = base_convert(++index, characters.length);

        for (var i = 0; i < converted.length; i++) {
            number += characters.charAt(converted[i]);
        }

        $(this).attr('data-letter', number);
    });
});​

My written Russian is admittedly bad, as you can see by my inability to count with letters, so change the letters object appropriately.

Demo: http://jsfiddle.net/JFFqn/14/



回答4:

Here is another solution for Cyrillic letters with pretty clear code: jsfiddle.net

(() => {
  const classname = 'ol.cyrillic',
        style     = document.createElement('style');

  document.head.appendChild(style);

  'абвгдежзиклмнопрстуфхцчшщэюя'.split('').forEach((c, i) =>
    style.sheet.insertRule(
      `${classname} > li:nth-child(${i+1})::before { 
         content: "${c})"
       }`, 0)
  );
})();

PS. You can convert this next-gen code to old one with Babel: babeljs.io