如何解决是否可以将 CSS 应用于字符的一半?
- 单个字符的
- JavaScript 用于跨文本或多个字符的自动化
- 为盲人或视障者的屏幕阅读器保留文本可访问性
第 1 部分:基本解决方案
//jsfiddle.net/arbel/pd9yB/1694/
这适用于任何动态文本或单个字符,并且都是自动化的。您需要做的就是在目标文本上添加一个类,剩下的就交给我们了。
此外,为盲人或视障人士的屏幕阅读器保留了原始文本的可访问性。
纯 CSS。您需要做的就是将.halfStyle
class 应用于包含您想要半样式的字符的每个元素。
对于包含字符的每个 span 元素,您可以创建一个数据属性,例如 here data-content="X"
,并在伪元素上使用content: attr(data-content);
,因此.halfStyle:before
该类将是动态的,您无需为每个实例硬编码它。
只需将textToHalfStyle
类添加到包含文本的元素。
// jQuery for automated mode
jQuery(function($) {
var text, chars, $el, i, output;
// Iterate over all class occurences
$('.textToHalfStyle').each(function(idx, el) {
$el = $(el);
text = $el.text();
chars = text.split('');
// Set the screen-reader text
$el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + text + '</span>');
// Reset output for appending
output = '';
// Iterate over all chars in the text
for (i = 0; i < chars.length; i++) {
// Create a styled element for each character and append to container
output += '<span aria-hidden="true" class="halfStyle" data-content="' + chars[i] + '">' + chars[i] + '</span>';
}
// Write to DOM only once
$el.append(output);
});
});
.halfStyle {
position: relative;
display: inline-block;
font-size: 80px; /* or any font size will work */
color: black; /* or transparent, any color */
overflow: hidden;
white-space: pre; /* to preserve the spaces from collapsing */
}
.halfStyle:before {
display: block;
z-index: 1;
position: absolute;
top: 0;
left: 0;
width: 50%;
content: attr(data-content); /* dynamic content for the pseudo element */
overflow: hidden;
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>Single Characters:</p>
<span class="halfStyle" data-content="X">X</span>
<span class="halfStyle" data-content="Y">Y</span>
<span class="halfStyle" data-content="Z">Z</span>
<span class="halfStyle" data-content="A">A</span>
<hr/>
<p>Automated:</p>
<span class="textToHalfStyle">Half-style, please.</span>
第 2 部分:高级解决方案 - 独立的左右部件
。
一切都是一样的,只有更高级的 CSS 才能发挥作用。
第 3 部分:混合搭配和改进
现在我们知道什么是可能的,让我们创建一些变化。
-水平半部分
-
没有文字阴影:
-
每个半部分独立的文本阴影的可能性:
Show code snippet
-垂直 1/3 零件
-
没有文字阴影:
-
每个 1/3 部分独立的文本阴影的可能性:
-水平 1/3 零件
-
没有文字阴影:
-
每个 1/3 部分独立的文本阴影的可能性:
-HalfStyle改进@KevinGranger
-@SamTremaine 对 HalfStyle 的 PeelingStyle改进
Show code snippet
(JSFiddle 演示和samtremaine.co.uk上)
第 4 部分:准备生产
可以在同一页面上的所需元素上使用定制的不同 Half-Style 样式集。您可以定义多个样式集并告诉插件使用哪一个。
该插件data-halfstyle="[-CustomClassName-]"
在目标.textToHalfStyle
元素上使用数据属性并自动进行所有必要的更改。
因此,只需在包含文本的元素上添加textToHalfStyle
class 和 data 属性data-halfstyle="[-CustomClassName-]"
。该插件将完成剩下的工作。
此外,CSS 样式集的类定义与[-CustomClassName-]
上面提到的部分匹配并链接到.halfStyle
,所以我们将有.halfStyle.[-CustomClassName-]
jQuery(function($) {
var halfstyle_text, halfstyle_chars, $halfstyle_el, halfstyle_i, halfstyle_output, halfstyle_style;
// Iterate over all class occurrences
$('.textToHalfStyle').each(function(idx, halfstyle_el) {
$halfstyle_el = $(halfstyle_el);
halfstyle_style = $halfstyle_el.data('halfstyle') || 'hs-base';
halfstyle_text = $halfstyle_el.text();
halfstyle_chars = halfstyle_text.split('');
// Set the screen-reader text
$halfstyle_el.html('<span style="position: absolute !important;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);">' + halfstyle_text + '</span>');
// Reset output for appending
halfstyle_output = '';
// Iterate over all chars in the text
for (halfstyle_i = 0; halfstyle_i < halfstyle_chars.length; halfstyle_i++) {
// Create a styled element for each character and append to container
halfstyle_output += '<span aria-hidden="true" class="halfStyle ' + halfstyle_style + '" data-content="' + halfstyle_chars[halfstyle_i] + '">' + halfstyle_chars[halfstyle_i] + '</span>';
}
// Write to DOM only once
$halfstyle_el.append(halfstyle_output);
});
});
/* start half-style hs-base */
.halfStyle.hs-base {
position: relative;
display: inline-block;
font-size: 80px; /* or any font size will work */
overflow: hidden;
white-space: pre; /* to preserve the spaces from collapsing */
color: #000; /* for demo purposes */
}
.halfStyle.hs-base:before {
display: block;
z-index: 1;
position: absolute;
top: 0;
width: 50%;
content: attr(data-content); /* dynamic content for the pseudo element */
pointer-events: none; /* so the base char is selectable by mouse */
overflow: hidden;
color: #f00; /* for demo purposes */
}
/* end half-style hs-base */
/* start half-style hs-horizontal-third */
.halfStyle.hs-horizontal-third { /* base char and also the bottom 1/3 */
position: relative;
display: inline-block;
font-size: 80px; /* or any font size will work */
color: transparent;
overflow: hidden;
white-space: pre; /* to preserve the spaces from collapsing */
color: #f0f;
text-shadow: 2px 2px 0px #0af; /* for demo purposes */
}
.halfStyle.hs-horizontal-third:before { /* creates the top 1/3 */
display: block;
z-index: 2;
position: absolute;
top: 0;
height: 33.33%;
content: attr(data-content); /* dynamic content for the pseudo element */
overflow: hidden;
pointer-events: none; /* so the base char is selectable by mouse */
color: #f00; /* for demo purposes */
text-shadow: 2px -2px 0px #fa0; /* for demo purposes */
}
.halfStyle.hs-horizontal-third:after { /* creates the middle 1/3 */
display: block;
position: absolute;
z-index: 1;
top: 0;
height: 66.66%;
content: attr(data-content); /* dynamic content for the pseudo element */
overflow: hidden;
pointer-events: none; /* so the base char is selectable by mouse */
color: #000; /* for demo purposes */
text-shadow: 2px 2px 0px #af0; /* for demo purposes */
}
/* end half-style hs-horizontal-third */
/* start half-style hs-PeelingStyle, by user SamTremaine on Stackoverflow.com */
.halfStyle.hs-PeelingStyle {
position: relative;
display: inline-block;
font-size: 68px;
color: rgba(0, 0, 0, 0.8);
overflow: hidden;
white-space: pre;
transform: rotate(4deg);
text-shadow: 2px 1px 3px rgba(0, 0, 0, 0.3);
}
.halfStyle.hs-PeelingStyle:before { /* creates the left part */
display: block;
z-index: 1;
position: absolute;
top: -0.5px;
left: -3px;
width: 100%;
content: attr(data-content);
overflow: hidden;
pointer-events: none;
color: #FFF;
transform: rotate(-4deg);
text-shadow: 0px 0px 1px #000;
}
/* end half-style hs-PeelingStyle */
/* start half-style hs-KevinGranger, by user KevinGranger on StackOverflow.com*/
.textToHalfStyle.hs-KevinGranger {
display: block;
margin: 200px 0 0 0;
text-align: center;
}
.halfStyle.hs-KevinGranger {
font-family: 'Libre Baskerville', serif;
position: relative;
display: inline-block;
width: 1;
font-size: 70px;
color: black;
overflow: hidden;
white-space: pre;
text-shadow: 1px 2px 0 white;
}
.halfStyle.hs-KevinGranger:before {
display: block;
z-index: 1;
position: absolute;
top: 0;
width: 50%;
content: attr(data-content); /* dynamic content for the pseudo element */
overflow: hidden;
color: white;
}
/* end half-style hs-KevinGranger
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
<span class="textToHalfStyle" data-halfstyle="hs-base">Half-style, please.</span>
</p>
<p>
<span class="textToHalfStyle" data-halfstyle="hs-horizontal-third">Half-style, please.</span>
</p>
<p>
<span class="textToHalfStyle" data-halfstyle="hs-PeelingStyle">Half-style, please.</span>
</p>
<p style="background-color:#000;">
<span class="textToHalfStyle" data-halfstyle="hs-KevinGranger">Half-style, please.</span>
</p>
解决方法
参数通过 assignment 传递。这背后的理由是双重的:
- 传入的参数其实是一个对象的引用(但是引用是按值传递的)
- 有些数据类型是可变的,但有些不是
所以:
- 如果你将一个可变对象传递给一个方法,该方法会获得对同一个对象的引用,你可以随心所欲地改变它,但是如果你在方法中重新绑定引用,外部作用域将一无所知,并且之后完成后,外部引用仍将指向原始对象。
- 如果将不可变对象传递给方法,仍然无法重新绑定外部引用,甚至无法改变对象。
为了更清楚,让我们举一些例子。
List - 可变类型
让我们尝试修改传递给方法的列表:
def try_to_change_list_contents(the_list):
print('got',the_list)
the_list.append('four')
print('changed to',the_list)
outer_list = ['one','two','three']
print('before,outer_list =',outer_list)
try_to_change_list_contents(outer_list)
print('after,outer_list)
输出:
before,outer_list = ['one','three']
got ['one','three']
changed to ['one','three','four']
after,'four']
由于传入的参数是对 的引用outer_list
,而不是它的副本,我们可以使用 mutating list 方法对其进行更改,并将更改反映在外部范围中。
现在让我们看看当我们尝试更改作为参数传入的引用时会发生什么:
def try_to_change_list_reference(the_list):
print('got',the_list)
the_list = ['and','we','can','not','lie']
print('set to',the_list)
outer_list = ['we','like','proper','English']
print('before,outer_list)
try_to_change_list_reference(outer_list)
print('after,outer_list = ['we','English']
got ['we','English']
set to ['and','lie']
after,'English']
由于the_list
参数是按值传递的,因此为它分配一个新列表对方法外的代码可以看到没有任何影响。这the_list
是outer_list
引用的副本,我们the_list
指向了一个新列表,但无法更改outer_list
指向的位置。
String - 不可变类型
它是不可变的,所以我们无法改变字符串的内容
现在,让我们尝试更改参考
def try_to_change_string_reference(the_string):
print('got',the_string)
the_string = 'In a kingdom by the sea'
print('set to',the_string)
outer_string = 'It was many and many a year ago'
print('before,outer_string =',outer_string)
try_to_change_string_reference(outer_string)
print('after,outer_string)
输出:
before,outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after,outer_string = It was many and many a year ago
同样,由于the_string
参数是按值传递的,因此为它分配一个新字符串对方法外部的代码没有任何影响。the_string
是引用的副本,outer_string
我们the_string
指向了一个新字符串,但无法更改outer_string
指向的位置。
我希望这能澄清一点。
编辑:有人指出,这并没有回答@David 最初提出的问题,“我可以做些什么来通过实际引用传递变量吗?”。让我们继续努力。
我们如何解决这个问题?
正如@Andrea 的回答所示,您可以返回新值。这不会改变传递事物的方式,但可以让您获得想要的信息:
def return_a_whole_new_string(the_string):
new_string = something_to_do_with_the_old_string(the_string)
return new_string
# then you could call it like
my_string = return_a_whole_new_string(my_string)
如果您真的想避免使用返回值,您可以创建一个类来保存您的值并将其传递给函数或使用现有类,如列表:
def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
new_string = something_to_do_with_the_old_string(stuff_to_change[0])
stuff_to_change[0] = new_string
# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)
do_something_with(wrapper[0])
虽然这看起来有点麻烦。